| 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 |