OLD | NEW |
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 Loading... |
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) && |
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 Loading... |
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 Loading... |
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) || |
| 164 CBS_len(&public_key) != 0 || |
150 !CBS_get_u16_length_prefixed(&tb, &signature) || | 165 !CBS_get_u16_length_prefixed(&tb, &signature) || |
151 !CBS_get_u16_length_prefixed(&tb, &extensions) || | 166 !CBS_get_u16_length_prefixed(&tb, &extensions) || |
152 tb_param != TB_PARAM_ECDSAP256 || | 167 tb_param != TB_PARAM_ECDSAP256 || |
153 (TokenBindingType(tb_type) != TokenBindingType::PROVIDED && | 168 (TokenBindingType(tb_type) != TokenBindingType::PROVIDED && |
154 TokenBindingType(tb_type) != TokenBindingType::REFERRED)) { | 169 TokenBindingType(tb_type) != TokenBindingType::REFERRED)) { |
155 return false; | 170 return false; |
156 } | 171 } |
157 | 172 |
158 TokenBinding token_binding; | 173 TokenBinding token_binding; |
159 token_binding.type = TokenBindingType(tb_type); | 174 token_binding.type = TokenBindingType(tb_type); |
160 token_binding.ec_point = std::string( | 175 token_binding.ec_point = std::string( |
161 reinterpret_cast<const char*>(CBS_data(&ec_point)), CBS_len(&ec_point)); | 176 reinterpret_cast<const char*>(CBS_data(&ec_point)), CBS_len(&ec_point)); |
162 token_binding.signature = | 177 token_binding.signature = |
163 std::string(reinterpret_cast<const char*>(CBS_data(&signature)), | 178 std::string(reinterpret_cast<const char*>(CBS_data(&signature)), |
164 CBS_len(&signature)); | 179 CBS_len(&signature)); |
165 token_bindings->push_back(token_binding); | 180 token_bindings->push_back(token_binding); |
166 } | 181 } |
167 return true; | 182 return true; |
168 } | 183 } |
169 | 184 |
170 bool VerifyEKMSignature(base::StringPiece ec_point, | 185 bool VerifyTokenBindingSignature(base::StringPiece ec_point, |
171 base::StringPiece signature, | 186 base::StringPiece signature, |
172 base::StringPiece ekm) { | 187 TokenBindingType type, |
| 188 base::StringPiece ekm) { |
173 if (ec_point.size() != kUncompressedPointLen - 1) | 189 if (ec_point.size() != kUncompressedPointLen - 1) |
174 return false; | 190 return false; |
175 uint8_t x9_62_ec_point[kUncompressedPointLen]; | 191 uint8_t x9_62_ec_point[kUncompressedPointLen]; |
176 x9_62_ec_point[0] = 4; | 192 x9_62_ec_point[0] = 4; |
177 memcpy(x9_62_ec_point + 1, ec_point.data(), kUncompressedPointLen - 1); | 193 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)); | 194 crypto::ScopedEC_Key key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); |
179 EC_KEY* keyp = key.get(); | 195 EC_KEY* keyp = key.get(); |
180 crypto::ScopedEC_POINT pub_key(EC_POINT_new(EC_KEY_get0_group(keyp))); | 196 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(), | 197 if (!EC_POINT_oct2point(EC_KEY_get0_group(keyp), pub_key.get(), |
182 x9_62_ec_point, kUncompressedPointLen, nullptr) || | 198 x9_62_ec_point, kUncompressedPointLen, nullptr) || |
183 !EC_KEY_set_public_key(keyp, pub_key.get())) { | 199 !EC_KEY_set_public_key(keyp, pub_key.get())) { |
184 return false; | 200 return false; |
185 } | 201 } |
186 | 202 |
| 203 crypto::ScopedEVP_MD_CTX digest_ctx(EVP_MD_CTX_create()); |
| 204 uint8_t tb_type = static_cast<uint8_t>(type); |
| 205 uint8_t key_type = static_cast<uint8_t>(TB_PARAM_ECDSAP256); |
| 206 uint8_t digest[EVP_MAX_MD_SIZE]; |
| 207 unsigned int digest_len; |
| 208 if (!EVP_DigestInit(digest_ctx.get(), EVP_sha256()) || |
| 209 !EVP_DigestUpdate(digest_ctx.get(), &tb_type, 1) || |
| 210 !EVP_DigestUpdate(digest_ctx.get(), &key_type, 1) || |
| 211 !EVP_DigestUpdate(digest_ctx.get(), ekm.data(), ekm.size()) || |
| 212 !EVP_DigestFinal_ex(digest_ctx.get(), digest, &digest_len)) { |
| 213 return false; |
| 214 } |
| 215 |
187 crypto::ScopedECDSA_SIG sig(RawToECDSA_SIG(keyp, signature)); | 216 crypto::ScopedECDSA_SIG sig(RawToECDSA_SIG(keyp, signature)); |
188 if (!sig) | 217 if (!sig) |
189 return false; | 218 return false; |
190 return !!ECDSA_do_verify(reinterpret_cast<const uint8_t*>(ekm.data()), | 219 return !!ECDSA_do_verify(digest, digest_len, sig.get(), keyp); |
191 ekm.size(), sig.get(), keyp); | |
192 } | 220 } |
193 | 221 |
194 } // namespace net | 222 } // namespace net |
OLD | NEW |