Upstream version 6.34.113.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / browser / installer / xpk_package.cc
1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "xwalk/application/browser/installer/xpk_package.h"
6
7 #include "base/file_util.h"
8 #include "crypto/signature_verifier.h"
9 #include "xwalk/application/common/id_util.h"
10
11 namespace xwalk {
12 namespace application {
13
14 const uint8 kSignatureAlgorithm[15] = {
15   0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
16   0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00
17 };
18
19 const char XPKPackage::kXPKPackageHeaderMagic[] = "CrWk";
20
21 XPKPackage::~XPKPackage() {
22 }
23
24 XPKPackage::XPKPackage(const base::FilePath& path)
25   : Package(path) {
26   if (!base::PathExists(path))
27     return;
28   scoped_ptr<ScopedStdioHandle> file(
29       new ScopedStdioHandle(base::OpenFile(path, "rb")));
30   file_ = file.Pass();
31   size_t len = fread(&header_, 1, sizeof(header_), file_->get());
32   is_valid_ = false;
33   if (len < sizeof(header_))
34     return;
35   if (!strncmp(XPKPackage::kXPKPackageHeaderMagic,
36                header_.magic,
37                sizeof(header_.magic)) &&
38       header_.key_size > 0 &&
39       header_.key_size <= XPKPackage::kMaxPublicKeySize &&
40       header_.signature_size > 0 &&
41       header_.signature_size <= XPKPackage::kMaxSignatureKeySize) {
42       is_valid_ = true;
43       zip_addr_ = sizeof(header_) + header_.key_size + header_.signature_size;
44         fseek(file_->get(), sizeof(header_), SEEK_SET);
45         key_.resize(header_.key_size);
46         size_t len = fread(
47             &key_.front(), sizeof(uint8), header_.key_size, file_->get());
48         if (len < header_.key_size)
49           is_valid_ = false;
50
51         signature_.resize(header_.signature_size);
52         len = fread(&signature_.front(),
53                     sizeof(uint8),
54                     header_.signature_size,
55                     file_->get());
56         if (len < header_.signature_size)
57           is_valid_ = false;
58
59         if (!VerifySignature())
60           is_valid_ = false;
61
62         std::string public_key =
63             std::string(reinterpret_cast<char*>(&key_.front()), key_.size());
64         id_ = GenerateId(public_key);
65   }
66   return;
67 }
68
69 bool XPKPackage::VerifySignature() {
70 // Set the file read position to the beginning of compressed resource file,
71 // which is behind the magic header, public key and signature key.
72   fseek(file_->get(), zip_addr_, SEEK_SET);
73   crypto::SignatureVerifier verifier;
74   if (!verifier.VerifyInit(kSignatureAlgorithm,
75                            sizeof(kSignatureAlgorithm),
76                            &signature_.front(),
77                            signature_.size(),
78                            &key_.front(),
79                            key_.size()))
80     return false;
81   unsigned char buf[1 << 12];
82   size_t len = 0;
83   while ((len = fread(buf, 1, sizeof(buf), file_->get())) > 0)
84     verifier.VerifyUpdate(buf, len);
85   if (!verifier.VerifyFinal())
86     return false;
87
88   return true;
89 }
90
91 bool XPKPackage::Extract(base::FilePath* target_path) {
92   if (is_extracted_) {
93     *target_path = temp_dir_.path();
94     return true;
95   }
96
97   if (!IsValid()) {
98     LOG(ERROR) << "The XPK file is not valid.";
99     return false;
100   }
101
102   return Package::Extract(target_path);
103 }
104
105 }  // namespace application
106 }  // namespace xwalk