Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: net/ssl/token_binding.cc

Issue 2337253004: Update Token Binding code to the latest drafts (Closed)
Patch Set: Fix compilation error in unit_tests Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/ssl/token_binding.h" 5 #include "net/ssl/token_binding.h"
6 6
7 #include <openssl/bytestring.h> 7 #include <openssl/bytestring.h>
8 #include <openssl/ec.h> 8 #include <openssl/ec.h>
9 #include <openssl/ec_key.h> 9 #include <openssl/ec_key.h>
10 #include <openssl/evp.h> 10 #include <openssl/evp.h>
(...skipping 14 matching lines...) Expand all
25 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key->key()); 25 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key->key());
26 DCHECK(ec_key); 26 DCHECK(ec_key);
27 27
28 uint8_t point_buf[kUncompressedPointLen]; 28 uint8_t point_buf[kUncompressedPointLen];
29 if (EC_POINT_point2oct( 29 if (EC_POINT_point2oct(
30 EC_KEY_get0_group(ec_key), EC_KEY_get0_public_key(ec_key), 30 EC_KEY_get0_group(ec_key), EC_KEY_get0_public_key(ec_key),
31 POINT_CONVERSION_UNCOMPRESSED, point_buf, kUncompressedPointLen, 31 POINT_CONVERSION_UNCOMPRESSED, point_buf, kUncompressedPointLen,
32 NULL) != kUncompressedPointLen) { 32 NULL) != kUncompressedPointLen) {
33 return false; 33 return false;
34 } 34 }
35 CBB ec_point; 35 CBB public_key, ec_point;
36 return CBB_add_u8(out, TB_PARAM_ECDSAP256) && 36 return CBB_add_u8(out, TB_PARAM_ECDSAP256) &&
37 CBB_add_u8_length_prefixed(out, &ec_point) && 37 CBB_add_u16_length_prefixed(out, &public_key) &&
38 CBB_add_u8_length_prefixed(&public_key, &ec_point) &&
davidben 2016/09/19 21:24:14 I... okay. They could also have said: struct {
nharper 2016/09/19 22:32:23 Maybe that can be changed in a future draft.
38 CBB_add_bytes(&ec_point, point_buf + 1, kUncompressedPointLen - 1) && 39 CBB_add_bytes(&ec_point, point_buf + 1, kUncompressedPointLen - 1) &&
39 CBB_flush(out); 40 CBB_flush(out);
40 } 41 }
41 42
42 bool ECDSA_SIGToRaw(ECDSA_SIG* ec_sig, EC_KEY* ec, std::vector<uint8_t>* out) { 43 bool ECDSA_SIGToRaw(ECDSA_SIG* ec_sig, EC_KEY* ec, std::vector<uint8_t>* out) {
43 const EC_GROUP* group = EC_KEY_get0_group(ec); 44 const EC_GROUP* group = EC_KEY_get0_group(ec);
44 const BIGNUM* order = EC_GROUP_get0_order(group); 45 const BIGNUM* order = EC_GROUP_get0_order(group);
45 size_t len = BN_num_bytes(order); 46 size_t len = BN_num_bytes(order);
46 out->resize(2 * len); 47 out->resize(2 * len);
47 if (!BN_bn2bin_padded(out->data(), len, ec_sig->r) || 48 if (!BN_bn2bin_padded(out->data(), len, ec_sig->r) ||
(...skipping 13 matching lines...) Expand all
61 const uint8_t* sigp = reinterpret_cast<const uint8_t*>(sig.data()); 62 const uint8_t* sigp = reinterpret_cast<const uint8_t*>(sig.data());
62 if (!BN_bin2bn(sigp, group_size, raw_sig->r) || 63 if (!BN_bin2bn(sigp, group_size, raw_sig->r) ||
63 !BN_bin2bn(sigp + group_size, group_size, raw_sig->s)) { 64 !BN_bin2bn(sigp + group_size, group_size, raw_sig->s)) {
64 return nullptr; 65 return nullptr;
65 } 66 }
66 return raw_sig.release(); 67 return raw_sig.release();
67 } 68 }
68 69
69 } // namespace 70 } // namespace
70 71
71 bool SignTokenBindingEkm(base::StringPiece ekm, 72 bool CreateTokenBindingSignature(base::StringPiece ekm,
72 crypto::ECPrivateKey* key, 73 TokenBindingType type,
73 std::vector<uint8_t>* out) { 74 crypto::ECPrivateKey* key,
74 const uint8_t* ekm_data = reinterpret_cast<const uint8_t*>(ekm.data()); 75 std::vector<uint8_t>* out) {
76 crypto::ScopedEVP_MD_CTX digest_ctx(EVP_MD_CTX_create());
77 uint8_t tb_type = static_cast<uint8_t>(type);
78 uint8_t key_type = static_cast<uint8_t>(TB_PARAM_ECDSAP256);
79 uint8_t digest[EVP_MAX_MD_SIZE];
80 unsigned int digest_len;
81 if (!EVP_DigestInit(digest_ctx.get(), EVP_sha256()) ||
82 !EVP_DigestUpdate(digest_ctx.get(), &tb_type, 1) ||
83 !EVP_DigestUpdate(digest_ctx.get(), &key_type, 1) ||
84 !EVP_DigestUpdate(digest_ctx.get(), ekm.data(), ekm.size()) ||
85 !EVP_DigestFinal_ex(digest_ctx.get(), digest, &digest_len)) {
86 return false;
87 }
75 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key->key()); 88 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key->key());
76 if (!ec_key) 89 if (!ec_key)
77 return false; 90 return false;
78 crypto::ScopedECDSA_SIG sig(ECDSA_do_sign(ekm_data, ekm.size(), ec_key)); 91 crypto::ScopedECDSA_SIG sig(ECDSA_do_sign(digest, digest_len, ec_key));
79 if (!sig) 92 if (!sig)
80 return false; 93 return false;
81 return ECDSA_SIGToRaw(sig.get(), ec_key, out); 94 return ECDSA_SIGToRaw(sig.get(), ec_key, out);
82 } 95 }
83 96
84 Error BuildTokenBindingMessageFromTokenBindings( 97 Error BuildTokenBindingMessageFromTokenBindings(
85 const std::vector<base::StringPiece>& token_bindings, 98 const std::vector<base::StringPiece>& token_bindings,
86 std::string* out) { 99 std::string* out) {
87 CBB tb_message, child; 100 CBB tb_message, child;
88 if (!CBB_init(&tb_message, 0) || 101 if (!CBB_init(&tb_message, 0) ||
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 } 143 }
131 out->assign(reinterpret_cast<char*>(out_data), out_len); 144 out->assign(reinterpret_cast<char*>(out_data), out_len);
132 OPENSSL_free(out_data); 145 OPENSSL_free(out_data);
133 return OK; 146 return OK;
134 } 147 }
135 148
136 TokenBinding::TokenBinding() {} 149 TokenBinding::TokenBinding() {}
137 150
138 bool ParseTokenBindingMessage(base::StringPiece token_binding_message, 151 bool ParseTokenBindingMessage(base::StringPiece token_binding_message,
139 std::vector<TokenBinding>* token_bindings) { 152 std::vector<TokenBinding>* token_bindings) {
140 CBS tb_message, tb, ec_point, signature, extensions; 153 CBS tb_message, tb, public_key, ec_point, signature, extensions;
141 uint8_t tb_type, tb_param; 154 uint8_t tb_type, tb_param;
142 CBS_init(&tb_message, 155 CBS_init(&tb_message,
143 reinterpret_cast<const uint8_t*>(token_binding_message.data()), 156 reinterpret_cast<const uint8_t*>(token_binding_message.data()),
144 token_binding_message.size()); 157 token_binding_message.size());
145 if (!CBS_get_u16_length_prefixed(&tb_message, &tb)) 158 if (!CBS_get_u16_length_prefixed(&tb_message, &tb))
146 return false; 159 return false;
147 while (CBS_len(&tb)) { 160 while (CBS_len(&tb)) {
148 if (!CBS_get_u8(&tb, &tb_type) || !CBS_get_u8(&tb, &tb_param) || 161 if (!CBS_get_u8(&tb, &tb_type) || !CBS_get_u8(&tb, &tb_param) ||
149 !CBS_get_u8_length_prefixed(&tb, &ec_point) || 162 !CBS_get_u16_length_prefixed(&tb, &public_key) ||
163 !CBS_get_u8_length_prefixed(&public_key, &ec_point) ||
davidben 2016/09/19 21:24:14 CBS_len(&public_key) != 0 ||
nharper 2016/09/19 22:32:23 CBS_get_u8_length_prefixed will return 0 (false) i
davidben 2016/09/19 22:35:40 It's to ensure there isn't garbage trailing the EC
nharper 2016/09/19 22:45:06 Oh! that makes sense. Done.
150 !CBS_get_u16_length_prefixed(&tb, &signature) || 164 !CBS_get_u16_length_prefixed(&tb, &signature) ||
151 !CBS_get_u16_length_prefixed(&tb, &extensions) || 165 !CBS_get_u16_length_prefixed(&tb, &extensions) ||
152 tb_param != TB_PARAM_ECDSAP256 || 166 tb_param != TB_PARAM_ECDSAP256 ||
153 (TokenBindingType(tb_type) != TokenBindingType::PROVIDED && 167 (TokenBindingType(tb_type) != TokenBindingType::PROVIDED &&
154 TokenBindingType(tb_type) != TokenBindingType::REFERRED)) { 168 TokenBindingType(tb_type) != TokenBindingType::REFERRED)) {
155 return false; 169 return false;
156 } 170 }
157 171
158 TokenBinding token_binding; 172 TokenBinding token_binding;
159 token_binding.type = TokenBindingType(tb_type); 173 token_binding.type = TokenBindingType(tb_type);
160 token_binding.ec_point = std::string( 174 token_binding.ec_point = std::string(
161 reinterpret_cast<const char*>(CBS_data(&ec_point)), CBS_len(&ec_point)); 175 reinterpret_cast<const char*>(CBS_data(&ec_point)), CBS_len(&ec_point));
162 token_binding.signature = 176 token_binding.signature =
163 std::string(reinterpret_cast<const char*>(CBS_data(&signature)), 177 std::string(reinterpret_cast<const char*>(CBS_data(&signature)),
164 CBS_len(&signature)); 178 CBS_len(&signature));
165 token_bindings->push_back(token_binding); 179 token_bindings->push_back(token_binding);
166 } 180 }
167 return true; 181 return true;
168 } 182 }
169 183
170 bool VerifyEKMSignature(base::StringPiece ec_point, 184 bool VerifyTokenBindingSignature(base::StringPiece ec_point,
171 base::StringPiece signature, 185 base::StringPiece signature,
172 base::StringPiece ekm) { 186 TokenBindingType type,
187 base::StringPiece ekm) {
173 if (ec_point.size() != kUncompressedPointLen - 1) 188 if (ec_point.size() != kUncompressedPointLen - 1)
174 return false; 189 return false;
175 uint8_t x9_62_ec_point[kUncompressedPointLen]; 190 uint8_t x9_62_ec_point[kUncompressedPointLen];
176 x9_62_ec_point[0] = 4; 191 x9_62_ec_point[0] = 4;
177 memcpy(x9_62_ec_point + 1, ec_point.data(), kUncompressedPointLen - 1); 192 memcpy(x9_62_ec_point + 1, ec_point.data(), kUncompressedPointLen - 1);
178 crypto::ScopedEC_Key key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); 193 crypto::ScopedEC_Key key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
179 EC_KEY* keyp = key.get(); 194 EC_KEY* keyp = key.get();
180 crypto::ScopedEC_POINT pub_key(EC_POINT_new(EC_KEY_get0_group(keyp))); 195 crypto::ScopedEC_POINT pub_key(EC_POINT_new(EC_KEY_get0_group(keyp)));
181 if (!EC_POINT_oct2point(EC_KEY_get0_group(keyp), pub_key.get(), 196 if (!EC_POINT_oct2point(EC_KEY_get0_group(keyp), pub_key.get(),
182 x9_62_ec_point, kUncompressedPointLen, nullptr) || 197 x9_62_ec_point, kUncompressedPointLen, nullptr) ||
183 !EC_KEY_set_public_key(keyp, pub_key.get())) { 198 !EC_KEY_set_public_key(keyp, pub_key.get())) {
184 return false; 199 return false;
185 } 200 }
186 201
202 crypto::ScopedEVP_MD_CTX digest_ctx(EVP_MD_CTX_create());
203 uint8_t tb_type = static_cast<uint8_t>(type);
204 uint8_t key_type = static_cast<uint8_t>(TB_PARAM_ECDSAP256);
205 uint8_t digest[EVP_MAX_MD_SIZE];
206 unsigned int digest_len;
207 if (!EVP_DigestInit(digest_ctx.get(), EVP_sha256()) ||
208 !EVP_DigestUpdate(digest_ctx.get(), &tb_type, 1) ||
209 !EVP_DigestUpdate(digest_ctx.get(), &key_type, 1) ||
210 !EVP_DigestUpdate(digest_ctx.get(), ekm.data(), ekm.size()) ||
211 !EVP_DigestFinal_ex(digest_ctx.get(), digest, &digest_len)) {
212 return false;
213 }
214
187 crypto::ScopedECDSA_SIG sig(RawToECDSA_SIG(keyp, signature)); 215 crypto::ScopedECDSA_SIG sig(RawToECDSA_SIG(keyp, signature));
188 if (!sig) 216 if (!sig)
189 return false; 217 return false;
190 return !!ECDSA_do_verify(reinterpret_cast<const uint8_t*>(ekm.data()), 218 return !!ECDSA_do_verify(digest, digest_len, sig.get(), keyp);
191 ekm.size(), sig.get(), keyp);
192 } 219 }
193 220
194 } // namespace net 221 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698