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