• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. 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 "google_apis/cup/client_update_protocol.h"
6 
7 #include <keyhi.h>
8 #include <pk11pub.h>
9 #include <seccomon.h>
10 
11 #include "base/logging.h"
12 #include "crypto/nss_util.h"
13 #include "crypto/scoped_nss_types.h"
14 
15 typedef scoped_ptr<CERTSubjectPublicKeyInfo,
16                    crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
17                                         SECKEY_DestroySubjectPublicKeyInfo> >
18     ScopedCERTSubjectPublicKeyInfo;
19 
~ClientUpdateProtocol()20 ClientUpdateProtocol::~ClientUpdateProtocol() {
21   if (public_key_)
22     SECKEY_DestroyPublicKey(public_key_);
23 }
24 
LoadPublicKey(const base::StringPiece & public_key)25 bool ClientUpdateProtocol::LoadPublicKey(const base::StringPiece& public_key) {
26   crypto::EnsureNSSInit();
27 
28   // The binary blob |public_key| is expected to be a DER-encoded ASN.1
29   // Subject Public Key Info.
30   SECItem spki_item;
31   spki_item.type = siBuffer;
32   spki_item.data =
33       reinterpret_cast<unsigned char*>(const_cast<char*>(public_key.data()));
34   spki_item.len = static_cast<unsigned int>(public_key.size());
35 
36   ScopedCERTSubjectPublicKeyInfo spki(
37       SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
38   if (!spki.get())
39     return false;
40 
41   public_key_ = SECKEY_ExtractPublicKey(spki.get());
42   if (!public_key_)
43     return false;
44 
45   if (!PublicKeyLength())
46     return false;
47 
48   return true;
49 }
50 
PublicKeyLength()51 size_t ClientUpdateProtocol::PublicKeyLength() {
52   if (!public_key_)
53     return 0;
54 
55   return SECKEY_PublicKeyStrength(public_key_);
56 }
57 
EncryptKeySource(const std::vector<uint8> & key_source)58 bool ClientUpdateProtocol::EncryptKeySource(
59     const std::vector<uint8>& key_source) {
60   // WARNING: This call bypasses the usual PKCS #1 padding and does direct RSA
61   // exponentiation.  This is not secure without taking measures to ensure that
62   // the contents of r are suitable.  This is done to remain compatible with
63   // the implementation on the Google Update servers; don't copy-paste this
64   // code arbitrarily and expect it to work and/or remain secure!
65   if (!public_key_)
66     return false;
67 
68   size_t keysize = SECKEY_PublicKeyStrength(public_key_);
69   if (key_source.size() != keysize)
70     return false;
71 
72   encrypted_key_source_.resize(keysize);
73   return SECSuccess == PK11_PubEncryptRaw(
74       public_key_,
75       &encrypted_key_source_[0],
76       const_cast<unsigned char*>(&key_source[0]),
77       key_source.size(),
78       NULL);
79 }
80 
81