Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/openssl_platform_key.h" | 5 #include "net/ssl/openssl_platform_key.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <NCrypt.h> | 8 #include <NCrypt.h> |
| 9 | 9 |
| 10 #include <string.h> | 10 #include <string.h> |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 const KeyExData* RsaGetExData(const RSA* rsa) { | 183 const KeyExData* RsaGetExData(const RSA* rsa) { |
| 184 return reinterpret_cast<const KeyExData*>( | 184 return reinterpret_cast<const KeyExData*>( |
| 185 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index())); | 185 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index())); |
| 186 } | 186 } |
| 187 | 187 |
| 188 size_t RsaMethodSize(const RSA* rsa) { | 188 size_t RsaMethodSize(const RSA* rsa) { |
| 189 const KeyExData* ex_data = RsaGetExData(rsa); | 189 const KeyExData* ex_data = RsaGetExData(rsa); |
| 190 return (ex_data->key_length + 7) / 8; | 190 return (ex_data->key_length + 7) / 8; |
| 191 } | 191 } |
| 192 | 192 |
| 193 // Signs |in| using |rsa| with PKCS #1 padding. If |hash_nid| is NID_md5_sha1, | 193 int RsaMethodSign(int hash_nid, |
| 194 // |in| is a TLS MD5/SHA-1 concatenation and should be signed as-is. Otherwise | |
| 195 // |in| is a standard hash function and should be prefixed with the | |
| 196 // corresponding DigestInfo before signing. The signature is written to |out| | |
| 197 // and its length written to |*out_len|. This function returns true on success | |
| 198 // and false on failure. | |
| 199 bool RsaSignPKCS1(const RSA* rsa, | |
| 200 int hash_nid, | |
| 201 const uint8_t* in, | 194 const uint8_t* in, |
| 202 size_t in_len, | 195 unsigned in_len, |
| 203 uint8_t* out, | 196 uint8_t* out, |
| 204 size_t max_out, | 197 unsigned* out_len, |
| 205 size_t* out_len) { | 198 const RSA* rsa) { |
| 199 // TODO(davidben): Switch BoringSSL's sign hook to using size_t rather than | |
| 200 // unsigned. | |
| 206 const KeyExData* ex_data = RsaGetExData(rsa); | 201 const KeyExData* ex_data = RsaGetExData(rsa); |
| 207 if (!ex_data) { | 202 if (!ex_data) { |
| 208 NOTREACHED(); | 203 NOTREACHED(); |
| 209 OPENSSL_PUT_ERROR(RSA, RSA_sign, ERR_R_INTERNAL_ERROR); | 204 OPENSSL_PUT_ERROR(RSA, RSA_sign, ERR_R_INTERNAL_ERROR); |
| 210 return false; | 205 return 0; |
| 211 } | 206 } |
| 212 | 207 |
| 213 if (ex_data->key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) { | 208 if (ex_data->key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) { |
| 214 BCRYPT_PKCS1_PADDING_INFO rsa_padding_info; | 209 BCRYPT_PKCS1_PADDING_INFO rsa_padding_info; |
| 215 switch (hash_nid) { | 210 switch (hash_nid) { |
| 216 case NID_md5_sha1: | 211 case NID_md5_sha1: |
| 217 rsa_padding_info.pszAlgId = nullptr; | 212 rsa_padding_info.pszAlgId = nullptr; |
| 218 break; | 213 break; |
| 219 case NID_sha1: | 214 case NID_sha1: |
| 220 rsa_padding_info.pszAlgId = BCRYPT_SHA1_ALGORITHM; | 215 rsa_padding_info.pszAlgId = BCRYPT_SHA1_ALGORITHM; |
| 221 break; | 216 break; |
| 222 case NID_sha256: | 217 case NID_sha256: |
| 223 rsa_padding_info.pszAlgId = BCRYPT_SHA256_ALGORITHM; | 218 rsa_padding_info.pszAlgId = BCRYPT_SHA256_ALGORITHM; |
| 224 break; | 219 break; |
| 225 case NID_sha384: | 220 case NID_sha384: |
| 226 rsa_padding_info.pszAlgId = BCRYPT_SHA384_ALGORITHM; | 221 rsa_padding_info.pszAlgId = BCRYPT_SHA384_ALGORITHM; |
| 227 break; | 222 break; |
| 228 case NID_sha512: | 223 case NID_sha512: |
| 229 rsa_padding_info.pszAlgId = BCRYPT_SHA512_ALGORITHM; | 224 rsa_padding_info.pszAlgId = BCRYPT_SHA512_ALGORITHM; |
| 230 break; | 225 break; |
| 231 default: | 226 default: |
| 232 OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 227 OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 233 return false; | 228 return 0; |
| 234 } | 229 } |
| 235 | 230 |
| 236 DWORD signature_len; | 231 DWORD signature_len; |
| 237 SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()( | 232 SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()( |
| 238 ex_data->key->hNCryptKey, &rsa_padding_info, const_cast<PBYTE>(in), | 233 ex_data->key->hNCryptKey, &rsa_padding_info, const_cast<PBYTE>(in), |
| 239 in_len, out, max_out, &signature_len, BCRYPT_PAD_PKCS1); | 234 in_len, out, RSA_size(rsa), &signature_len, BCRYPT_PAD_PKCS1); |
|
Ryan Sleevi
2014/12/03 14:10:39
Is this entirely safe? Does RSA_size handle any sp
davidben
2014/12/03 16:01:38
RSA_size is the number of bytes needed to represen
| |
| 240 if (FAILED(ncrypt_status) || signature_len == 0) { | 235 if (FAILED(ncrypt_status) || signature_len == 0) { |
| 241 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 236 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
| 242 return false; | 237 return 0; |
| 243 } | 238 } |
| 244 *out_len = signature_len; | 239 *out_len = signature_len; |
| 245 return true; | 240 return 1; |
| 246 } | 241 } |
| 247 | 242 |
| 248 ALG_ID hash_alg; | 243 ALG_ID hash_alg; |
| 249 switch (hash_nid) { | 244 switch (hash_nid) { |
| 250 case NID_md5_sha1: | 245 case NID_md5_sha1: |
| 251 hash_alg = CALG_SSL3_SHAMD5; | 246 hash_alg = CALG_SSL3_SHAMD5; |
| 252 break; | 247 break; |
| 253 case NID_sha1: | 248 case NID_sha1: |
| 254 hash_alg = CALG_SHA1; | 249 hash_alg = CALG_SHA1; |
| 255 break; | 250 break; |
| 256 case NID_sha256: | 251 case NID_sha256: |
| 257 hash_alg = CALG_SHA_256; | 252 hash_alg = CALG_SHA_256; |
| 258 break; | 253 break; |
| 259 case NID_sha384: | 254 case NID_sha384: |
| 260 hash_alg = CALG_SHA_384; | 255 hash_alg = CALG_SHA_384; |
| 261 break; | 256 break; |
| 262 case NID_sha512: | 257 case NID_sha512: |
| 263 hash_alg = CALG_SHA_512; | 258 hash_alg = CALG_SHA_512; |
| 264 break; | 259 break; |
| 265 default: | 260 default: |
| 266 OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 261 OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 267 return false; | 262 return 0; |
| 268 } | 263 } |
| 269 | 264 |
| 270 HCRYPTHASH hash; | 265 HCRYPTHASH hash; |
| 271 if (!CryptCreateHash(ex_data->key->hCryptProv, hash_alg, 0, 0, &hash)) { | 266 if (!CryptCreateHash(ex_data->key->hCryptProv, hash_alg, 0, 0, &hash)) { |
| 272 PLOG(ERROR) << "CreateCreateHash failed"; | 267 PLOG(ERROR) << "CreateCreateHash failed"; |
| 273 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 268 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
| 274 return false; | 269 return 0; |
| 275 } | 270 } |
| 276 DWORD hash_len; | 271 DWORD hash_len; |
| 277 DWORD arg_len = sizeof(hash_len); | 272 DWORD arg_len = sizeof(hash_len); |
| 278 if (!CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hash_len), | 273 if (!CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hash_len), |
| 279 &arg_len, 0)) { | 274 &arg_len, 0)) { |
| 280 PLOG(ERROR) << "CryptGetHashParam HP_HASHSIZE failed"; | 275 PLOG(ERROR) << "CryptGetHashParam HP_HASHSIZE failed"; |
| 281 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 276 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
| 282 return false; | 277 return 0; |
| 283 } | 278 } |
| 284 if (hash_len != in_len) { | 279 if (hash_len != in_len) { |
| 285 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 280 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
| 286 return false; | 281 return 0; |
| 287 } | 282 } |
| 288 if (!CryptSetHashParam(hash, HP_HASHVAL, const_cast<BYTE*>(in), 0)) { | 283 if (!CryptSetHashParam(hash, HP_HASHVAL, const_cast<BYTE*>(in), 0)) { |
| 289 PLOG(ERROR) << "CryptSetHashParam HP_HASHVAL failed"; | 284 PLOG(ERROR) << "CryptSetHashParam HP_HASHVAL failed"; |
| 290 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 285 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
| 291 return false; | 286 return 0; |
| 292 } | 287 } |
| 293 DWORD signature_len = max_out; | 288 DWORD signature_len = RSA_size(rsa); |
| 294 if (!CryptSignHash(hash, ex_data->key->dwKeySpec, nullptr, 0, out, | 289 if (!CryptSignHash(hash, ex_data->key->dwKeySpec, nullptr, 0, out, |
| 295 &signature_len)) { | 290 &signature_len)) { |
| 296 PLOG(ERROR) << "CryptSignHash failed"; | 291 PLOG(ERROR) << "CryptSignHash failed"; |
| 297 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 292 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
| 298 return false; | 293 return 0; |
| 299 } | 294 } |
| 300 | 295 |
| 301 /* CryptoAPI signs in little-endian, so reverse it. */ | 296 /* CryptoAPI signs in little-endian, so reverse it. */ |
| 302 std::reverse(out, out + signature_len); | 297 std::reverse(out, out + signature_len); |
| 303 *out_len = signature_len; | 298 *out_len = signature_len; |
| 304 return true; | |
| 305 } | |
| 306 | |
| 307 int RsaMethodSign(int hash_nid, | |
| 308 const uint8_t* in, | |
| 309 unsigned in_len, | |
| 310 uint8_t* out, | |
| 311 unsigned* out_len, | |
| 312 const RSA* rsa) { | |
| 313 // TOD(davidben): Switch BoringSSL's sign hook to using size_t rather than | |
| 314 // unsigned. | |
| 315 size_t len; | |
| 316 if (!RsaSignPKCS1(rsa, hash_nid, in, in_len, out, RSA_size(rsa), &len)) | |
| 317 return 0; | |
| 318 *out_len = len; | |
| 319 return 1; | 299 return 1; |
| 320 } | 300 } |
| 321 | 301 |
| 322 int RsaMethodEncrypt(RSA* rsa, | 302 int RsaMethodEncrypt(RSA* rsa, |
| 323 size_t* out_len, | 303 size_t* out_len, |
| 324 uint8_t* out, | 304 uint8_t* out, |
| 325 size_t max_out, | 305 size_t max_out, |
| 326 const uint8_t* in, | 306 const uint8_t* in, |
| 327 size_t in_len, | 307 size_t in_len, |
| 328 int padding) { | 308 int padding) { |
| 329 NOTIMPLEMENTED(); | 309 NOTIMPLEMENTED(); |
| 330 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 310 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 331 return 0; | 311 return 0; |
| 332 } | 312 } |
| 333 | 313 |
| 334 int RsaMethodSignRaw(RSA* rsa, | 314 int RsaMethodSignRaw(RSA* rsa, |
| 335 size_t* out_len, | 315 size_t* out_len, |
| 336 uint8_t* out, | 316 uint8_t* out, |
| 337 size_t max_out, | 317 size_t max_out, |
| 338 const uint8_t* in, | 318 const uint8_t* in, |
| 339 size_t in_len, | 319 size_t in_len, |
| 340 int padding) { | 320 int padding) { |
| 341 DCHECK_EQ(RSA_PKCS1_PADDING, padding); | 321 NOTIMPLEMENTED(); |
| 342 if (padding != RSA_PKCS1_PADDING) { | 322 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 343 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE); | 323 return 0; |
| 344 return 0; | |
| 345 } | |
| 346 | |
| 347 // BoringSSL calls only sign_raw, not sign, in pre-TLS-1.2 MD5/SHA1 | |
| 348 // signatures. This hook is implemented only for that case. | |
| 349 // | |
| 350 // TODO(davidben): Make client auth in BoringSSL call RSA_sign with | |
| 351 // NID_md5_sha1. https://crbug.com/437023 | |
| 352 if (in_len != MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH) { | |
| 353 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_INVALID_MESSAGE_LENGTH); | |
| 354 return 0; | |
| 355 } | |
| 356 if (!RsaSignPKCS1(rsa, NID_md5_sha1, in, in_len, out, max_out, out_len)) | |
| 357 return 0; | |
| 358 return 1; | |
| 359 } | 324 } |
| 360 | 325 |
| 361 int RsaMethodDecrypt(RSA* rsa, | 326 int RsaMethodDecrypt(RSA* rsa, |
| 362 size_t* out_len, | 327 size_t* out_len, |
| 363 uint8_t* out, | 328 uint8_t* out, |
| 364 size_t max_out, | 329 size_t max_out, |
| 365 const uint8_t* in, | 330 const uint8_t* in, |
| 366 size_t in_len, | 331 size_t in_len, |
| 367 int padding) { | 332 int padding) { |
| 368 NOTIMPLEMENTED(); | 333 NOTIMPLEMENTED(); |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 case EVP_PKEY_RSA: | 666 case EVP_PKEY_RSA: |
| 702 return CreateRSAWrapper(key.Pass(), key_length); | 667 return CreateRSAWrapper(key.Pass(), key_length); |
| 703 case EVP_PKEY_EC: | 668 case EVP_PKEY_EC: |
| 704 return CreateECDSAWrapper(key.Pass(), key_length); | 669 return CreateECDSAWrapper(key.Pass(), key_length); |
| 705 default: | 670 default: |
| 706 return nullptr; | 671 return nullptr; |
| 707 } | 672 } |
| 708 } | 673 } |
| 709 | 674 |
| 710 } // namespace net | 675 } // namespace net |
| OLD | NEW |