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); |
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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 } | 464 } |
500 sig->r = BN_bin2bn(&raw_sig[0], degree, nullptr); | 465 sig->r = BN_bin2bn(&raw_sig[0], degree, nullptr); |
501 sig->s = BN_bin2bn(&raw_sig[degree], degree, nullptr); | 466 sig->s = BN_bin2bn(&raw_sig[degree], degree, nullptr); |
502 if (!sig->r || !sig->s) { | 467 if (!sig->r || !sig->s) { |
503 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 468 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
504 return 0; | 469 return 0; |
505 } | 470 } |
506 | 471 |
507 // Ensure the DER-encoded signature fits in the bounds. | 472 // Ensure the DER-encoded signature fits in the bounds. |
508 int len = i2d_ECDSA_SIG(sig.get(), nullptr); | 473 int len = i2d_ECDSA_SIG(sig.get(), nullptr); |
509 if (len < 0 || len > ECDSA_size(ec_key)) { | 474 if (len < 0 || static_cast<size_t>(len) > ECDSA_size(ec_key)) { |
510 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 475 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
511 return 0; | 476 return 0; |
512 } | 477 } |
513 | 478 |
514 len = i2d_ECDSA_SIG(sig.get(), &out_sig); | 479 len = i2d_ECDSA_SIG(sig.get(), &out_sig); |
515 if (len < 0) { | 480 if (len < 0) { |
516 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 481 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
517 return 0; | 482 return 0; |
518 } | 483 } |
519 *out_sig_len = len; | 484 *out_sig_len = len; |
(...skipping 181 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 |