OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 "components/gcm_driver/crypto/p256_key_util.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 #include <string.h> | |
10 #include <vector> | |
11 | |
12 #include "base/logging.h" | |
13 #include "base/memory/scoped_ptr.h" | |
14 #include "crypto/ec_private_key.h" | |
15 #include "crypto/scoped_nss_types.h" | |
16 | |
17 namespace gcm { | |
18 | |
19 namespace { | |
20 | |
21 // A P-256 field element consists of 32 bytes. | |
22 const size_t kFieldBytes = 32; | |
23 | |
24 } // namespace | |
25 | |
26 bool ComputeSharedP256Secret(const base::StringPiece& private_key, | |
27 const base::StringPiece& public_key_x509, | |
28 const base::StringPiece& peer_public_key, | |
29 std::string* out_shared_secret) { | |
30 DCHECK(out_shared_secret); | |
31 | |
32 scoped_ptr<crypto::ECPrivateKey> local_key_pair( | |
33 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | |
34 "" /* no password */, | |
35 std::vector<uint8_t>( | |
36 private_key.data(), private_key.data() + private_key.size()), | |
37 std::vector<uint8_t>( | |
38 public_key_x509.data(), | |
39 public_key_x509.data() + public_key_x509.size()))); | |
40 | |
41 if (!local_key_pair) { | |
42 DLOG(ERROR) << "Unable to create the local key pair."; | |
43 return false; | |
44 } | |
45 | |
46 SECKEYPublicKey public_key_peer; | |
47 memset(&public_key_peer, 0, sizeof(public_key_peer)); | |
48 | |
49 public_key_peer.keyType = ecKey; | |
50 // Both sides of a ECDH key exchange need to use the same EC params. | |
51 public_key_peer.u.ec.DEREncodedParams.len = | |
52 local_key_pair->public_key()->u.ec.DEREncodedParams.len; | |
53 public_key_peer.u.ec.DEREncodedParams.data = | |
54 local_key_pair->public_key()->u.ec.DEREncodedParams.data; | |
55 | |
56 public_key_peer.u.ec.publicValue.type = siBuffer; | |
57 public_key_peer.u.ec.publicValue.data = | |
58 reinterpret_cast<uint8_t*>(const_cast<char*>(peer_public_key.data())); | |
59 public_key_peer.u.ec.publicValue.len = peer_public_key.size(); | |
60 | |
61 // The NSS function performing ECDH key exchange is PK11_PubDeriveWithKDF. | |
62 // As this function is used for SSL/TLS's ECDH key exchanges it has many | |
63 // arguments, most of which are not required. Key derivation function CKD_NULL | |
64 // is used because the return value of |CalculateSharedKey| is the actual ECDH | |
65 // shared key, not any derived keys from it. | |
66 crypto::ScopedPK11SymKey premaster_secret( | |
67 PK11_PubDeriveWithKDF( | |
68 local_key_pair->key(), | |
69 &public_key_peer, | |
70 PR_FALSE /* isSender */, | |
71 nullptr /* randomA */, | |
72 nullptr /* randomB */, | |
73 CKM_ECDH1_DERIVE, | |
74 CKM_GENERIC_SECRET_KEY_GEN, | |
75 CKA_DERIVE, | |
76 0 /* keySize */, | |
77 CKD_NULL /* kdf */, | |
78 nullptr /* sharedData */, | |
79 nullptr /* wincx */)); | |
80 | |
81 if (!premaster_secret) { | |
82 DLOG(ERROR) << "Unable to derive the ECDH shared key."; | |
83 return false; | |
84 } | |
85 | |
86 if (PK11_ExtractKeyValue(premaster_secret.get()) != SECSuccess) { | |
87 DLOG(ERROR) << "Unable to extract the raw ECDH shared secret."; | |
88 return false; | |
89 } | |
90 | |
91 SECItem* key_data = PK11_GetKeyData(premaster_secret.get()); | |
92 if (!key_data || !key_data->data || key_data->len != kFieldBytes) { | |
93 DLOG(ERROR) << "The raw ECDH shared secret is invalid."; | |
94 return false; | |
95 } | |
96 | |
97 out_shared_secret->assign( | |
98 reinterpret_cast<char*>(key_data->data), key_data->len); | |
99 return true; | |
100 } | |
101 | |
102 } // namespace gcm | |
OLD | NEW |