OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/renderer/webcrypto/webcrypto_impl.h" | 5 #include "content/renderer/webcrypto/webcrypto_impl.h" |
6 | 6 |
7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
9 #include <sechash.h> | 9 #include <sechash.h> |
10 | 10 |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 293 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
294 | 294 |
295 const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams(); | 295 const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams(); |
296 if (!params) | 296 if (!params) |
297 return Status::ErrorUnexpected(); | 297 return Status::ErrorUnexpected(); |
298 | 298 |
299 // TODO(eroman): The spec doesn't define the default value. Assume 128 for now | 299 // TODO(eroman): The spec doesn't define the default value. Assume 128 for now |
300 // since that is the maximum tag length: | 300 // since that is the maximum tag length: |
301 // http://www.w3.org/2012/webcrypto/track/issues/46 | 301 // http://www.w3.org/2012/webcrypto/track/issues/46 |
302 unsigned tag_length_bits = 128; | 302 unsigned tag_length_bits = 128; |
303 if (params->hasTagLengthBits()) { | 303 if (params->hasTagLengthBits()) |
304 tag_length_bits = params->optionalTagLengthBits(); | 304 tag_length_bits = params->optionalTagLengthBits(); |
305 } | |
306 | 305 |
307 if (tag_length_bits > 128 || (tag_length_bits % 8) != 0) { | 306 if (tag_length_bits > 128 || (tag_length_bits % 8) != 0) |
308 return Status::ErrorInvalidAesGcmTagLength(); | 307 return Status::ErrorInvalidAesGcmTagLength(); |
309 } | 308 |
310 unsigned tag_length_bytes = tag_length_bits / 8; | 309 unsigned tag_length_bytes = tag_length_bits / 8; |
311 | 310 |
312 CK_GCM_PARAMS gcm_params = {0}; | 311 CK_GCM_PARAMS gcm_params = {0}; |
313 gcm_params.pIv = | 312 gcm_params.pIv = |
314 const_cast<unsigned char*>(algorithm.aesGcmParams()->iv().data()); | 313 const_cast<unsigned char*>(algorithm.aesGcmParams()->iv().data()); |
315 gcm_params.ulIvLen = algorithm.aesGcmParams()->iv().size(); | 314 gcm_params.ulIvLen = algorithm.aesGcmParams()->iv().size(); |
316 | 315 |
317 gcm_params.pAAD = | 316 gcm_params.pAAD = |
318 const_cast<unsigned char*>(params->optionalAdditionalData().data()); | 317 const_cast<unsigned char*>(params->optionalAdditionalData().data()); |
319 gcm_params.ulAADLen = params->optionalAdditionalData().size(); | 318 gcm_params.ulAADLen = params->optionalAdditionalData().size(); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. | 437 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. |
439 // Currently only supporting symmetric. | 438 // Currently only supporting symmetric. |
440 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; | 439 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; |
441 // Flags are verified at the Blink layer; here the flags are set to all | 440 // Flags are verified at the Blink layer; here the flags are set to all |
442 // possible operations for this key type. | 441 // possible operations for this key type. |
443 CK_FLAGS flags = 0; | 442 CK_FLAGS flags = 0; |
444 | 443 |
445 switch (algorithm.id()) { | 444 switch (algorithm.id()) { |
446 case blink::WebCryptoAlgorithmIdHmac: { | 445 case blink::WebCryptoAlgorithmIdHmac: { |
447 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); | 446 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
448 if (!params) { | 447 if (!params) |
449 return Status::ErrorUnexpected(); | 448 return Status::ErrorUnexpected(); |
450 } | |
451 | 449 |
452 mechanism = WebCryptoHashToHMACMechanism(params->hash()); | 450 mechanism = WebCryptoHashToHMACMechanism(params->hash()); |
453 if (mechanism == CKM_INVALID_MECHANISM) { | 451 if (mechanism == CKM_INVALID_MECHANISM) |
454 return Status::ErrorUnsupported(); | 452 return Status::ErrorUnsupported(); |
455 } | |
456 | 453 |
457 flags |= CKF_SIGN | CKF_VERIFY; | 454 flags |= CKF_SIGN | CKF_VERIFY; |
458 | 455 |
459 break; | 456 break; |
460 } | 457 } |
461 case blink::WebCryptoAlgorithmIdAesCbc: { | 458 case blink::WebCryptoAlgorithmIdAesCbc: { |
462 mechanism = CKM_AES_CBC; | 459 mechanism = CKM_AES_CBC; |
463 flags |= CKF_ENCRYPT | CKF_DECRYPT; | 460 flags |= CKF_ENCRYPT | CKF_DECRYPT; |
464 break; | 461 break; |
465 } | 462 } |
(...skipping 25 matching lines...) Expand all Loading... |
491 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); | 488 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); |
492 crypto::ScopedPK11SymKey pk11_sym_key( | 489 crypto::ScopedPK11SymKey pk11_sym_key( |
493 PK11_ImportSymKeyWithFlags(slot.get(), | 490 PK11_ImportSymKeyWithFlags(slot.get(), |
494 mechanism, | 491 mechanism, |
495 PK11_OriginUnwrap, | 492 PK11_OriginUnwrap, |
496 CKA_FLAGS_ONLY, | 493 CKA_FLAGS_ONLY, |
497 &key_item, | 494 &key_item, |
498 flags, | 495 flags, |
499 false, | 496 false, |
500 NULL)); | 497 NULL)); |
501 if (!pk11_sym_key.get()) { | 498 if (!pk11_sym_key.get()) |
502 return Status::Error(); | 499 return Status::Error(); |
503 } | |
504 | 500 |
505 *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()), | 501 *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()), |
506 type, extractable, algorithm, usage_mask); | 502 type, extractable, algorithm, usage_mask); |
507 return Status::Success(); | 503 return Status::Success(); |
508 } | 504 } |
509 | 505 |
510 Status ExportKeyInternalRaw( | 506 Status ExportKeyInternalRaw( |
511 const blink::WebCryptoKey& key, | 507 const blink::WebCryptoKey& key, |
512 blink::WebArrayBuffer* buffer) { | 508 blink::WebArrayBuffer* buffer) { |
513 | 509 |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 | 692 |
697 Status SignHmac( | 693 Status SignHmac( |
698 const blink::WebCryptoAlgorithm& algorithm, | 694 const blink::WebCryptoAlgorithm& algorithm, |
699 const blink::WebCryptoKey& key, | 695 const blink::WebCryptoKey& key, |
700 const unsigned char* data, | 696 const unsigned char* data, |
701 unsigned data_size, | 697 unsigned data_size, |
702 blink::WebArrayBuffer* buffer) { | 698 blink::WebArrayBuffer* buffer) { |
703 DCHECK_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); | 699 DCHECK_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); |
704 | 700 |
705 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); | 701 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
706 if (!params) { | 702 if (!params) |
707 return Status::ErrorUnexpected(); | 703 return Status::ErrorUnexpected(); |
708 } | |
709 | 704 |
710 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 705 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
711 | 706 |
712 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), | 707 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), |
713 WebCryptoHashToHMACMechanism(params->hash())); | 708 WebCryptoHashToHMACMechanism(params->hash())); |
714 | 709 |
715 SECItem param_item = { siBuffer, NULL, 0 }; | 710 SECItem param_item = { siBuffer, NULL, 0 }; |
716 SECItem data_item = { | 711 SECItem data_item = { |
717 siBuffer, | 712 siBuffer, |
718 const_cast<unsigned char*>(data), | 713 const_cast<unsigned char*>(data), |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 const blink::WebCryptoKey& key, | 746 const blink::WebCryptoKey& key, |
752 const unsigned char* signature, | 747 const unsigned char* signature, |
753 unsigned signature_size, | 748 unsigned signature_size, |
754 const unsigned char* data, | 749 const unsigned char* data, |
755 unsigned data_size, | 750 unsigned data_size, |
756 bool* signature_match) { | 751 bool* signature_match) { |
757 DCHECK_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); | 752 DCHECK_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); |
758 | 753 |
759 blink::WebArrayBuffer result; | 754 blink::WebArrayBuffer result; |
760 Status status = SignHmac(algorithm, key, data, data_size, &result); | 755 Status status = SignHmac(algorithm, key, data, data_size, &result); |
761 if (status.IsError()) { | 756 if (status.IsError()) |
762 return status; | 757 return status; |
763 } | |
764 | 758 |
765 // Handling of truncated signatures is underspecified in the WebCrypto | 759 // Handling of truncated signatures is underspecified in the WebCrypto |
766 // spec, so here we fail verification if a truncated signature is being | 760 // spec, so here we fail verification if a truncated signature is being |
767 // verified. | 761 // verified. |
768 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 | 762 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 |
769 *signature_match = | 763 *signature_match = |
770 result.byteLength() == signature_size && | 764 result.byteLength() == signature_size && |
771 crypto::SecureMemEqual(result.data(), signature, signature_size); | 765 crypto::SecureMemEqual(result.data(), signature, signature_size); |
772 | 766 |
773 return Status::Success(); | 767 return Status::Success(); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 SECKEYPublicKey* sec_public_key; | 1029 SECKEYPublicKey* sec_public_key; |
1036 crypto::ScopedSECKEYPrivateKey scoped_sec_private_key( | 1030 crypto::ScopedSECKEYPrivateKey scoped_sec_private_key( |
1037 PK11_GenerateKeyPairWithOpFlags(slot.get(), | 1031 PK11_GenerateKeyPairWithOpFlags(slot.get(), |
1038 CKM_RSA_PKCS_KEY_PAIR_GEN, | 1032 CKM_RSA_PKCS_KEY_PAIR_GEN, |
1039 &rsa_gen_params, | 1033 &rsa_gen_params, |
1040 &sec_public_key, | 1034 &sec_public_key, |
1041 attribute_flags, | 1035 attribute_flags, |
1042 operation_flags, | 1036 operation_flags, |
1043 operation_flags_mask, | 1037 operation_flags_mask, |
1044 NULL)); | 1038 NULL)); |
1045 if (!private_key) { | 1039 if (!private_key) |
1046 return Status::Error(); | 1040 return Status::Error(); |
1047 } | |
1048 | 1041 |
1049 *public_key = blink::WebCryptoKey::create( | 1042 *public_key = blink::WebCryptoKey::create( |
1050 new PublicKeyHandle(crypto::ScopedSECKEYPublicKey(sec_public_key)), | 1043 new PublicKeyHandle(crypto::ScopedSECKEYPublicKey(sec_public_key)), |
1051 blink::WebCryptoKeyTypePublic, | 1044 blink::WebCryptoKeyTypePublic, |
1052 true, | 1045 true, |
1053 algorithm, | 1046 algorithm, |
1054 usage_mask); | 1047 usage_mask); |
1055 *private_key = blink::WebCryptoKey::create( | 1048 *private_key = blink::WebCryptoKey::create( |
1056 new PrivateKeyHandle(scoped_sec_private_key.Pass()), | 1049 new PrivateKeyHandle(scoped_sec_private_key.Pass()), |
1057 blink::WebCryptoKeyTypePrivate, | 1050 blink::WebCryptoKeyTypePrivate, |
(...skipping 20 matching lines...) Expand all Loading... |
1078 // Ensure the key length is a multiple of 8 bits. Let NSS verify further | 1071 // Ensure the key length is a multiple of 8 bits. Let NSS verify further |
1079 // algorithm-specific length restrictions. | 1072 // algorithm-specific length restrictions. |
1080 if (params->lengthBits() % 8) | 1073 if (params->lengthBits() % 8) |
1081 return Status::ErrorGenerateKeyLength(); | 1074 return Status::ErrorGenerateKeyLength(); |
1082 *keylen_bytes = params->lengthBits() / 8; | 1075 *keylen_bytes = params->lengthBits() / 8; |
1083 break; | 1076 break; |
1084 } | 1077 } |
1085 case blink::WebCryptoAlgorithmIdHmac: { | 1078 case blink::WebCryptoAlgorithmIdHmac: { |
1086 const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); | 1079 const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); |
1087 DCHECK(params); | 1080 DCHECK(params); |
1088 if (params->hasLengthBytes()) { | 1081 if (params->hasLengthBytes()) |
1089 *keylen_bytes = params->optionalLengthBytes(); | 1082 *keylen_bytes = params->optionalLengthBytes(); |
1090 } else { | 1083 else |
1091 *keylen_bytes = webcrypto::ShaBlockSizeBytes(params->hash().id()); | 1084 *keylen_bytes = webcrypto::ShaBlockSizeBytes(params->hash().id()); |
1092 } | |
1093 break; | 1085 break; |
1094 } | 1086 } |
1095 | 1087 |
1096 default: | 1088 default: |
1097 return Status::ErrorUnsupported(); | 1089 return Status::ErrorUnsupported(); |
1098 } | 1090 } |
1099 | 1091 |
1100 if (*keylen_bytes == 0) { | 1092 if (*keylen_bytes == 0) |
1101 return Status::ErrorGenerateKeyLength(); | 1093 return Status::ErrorGenerateKeyLength(); |
1102 } | |
1103 | 1094 |
1104 return Status::Success(); | 1095 return Status::Success(); |
1105 } | 1096 } |
1106 | 1097 |
1107 } // namespace | 1098 } // namespace |
1108 | 1099 |
1109 void WebCryptoImpl::Init() { | 1100 void WebCryptoImpl::Init() { |
1110 crypto::EnsureNSSInit(); | 1101 crypto::EnsureNSSInit(); |
1111 } | 1102 } |
1112 | 1103 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1159 return Status::ErrorUnsupported(); | 1150 return Status::ErrorUnsupported(); |
1160 } | 1151 } |
1161 } | 1152 } |
1162 | 1153 |
1163 Status WebCryptoImpl::DigestInternal( | 1154 Status WebCryptoImpl::DigestInternal( |
1164 const blink::WebCryptoAlgorithm& algorithm, | 1155 const blink::WebCryptoAlgorithm& algorithm, |
1165 const unsigned char* data, | 1156 const unsigned char* data, |
1166 unsigned data_size, | 1157 unsigned data_size, |
1167 blink::WebArrayBuffer* buffer) { | 1158 blink::WebArrayBuffer* buffer) { |
1168 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); | 1159 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); |
1169 if (hash_type == HASH_AlgNULL) { | 1160 if (hash_type == HASH_AlgNULL) |
1170 return Status::ErrorUnsupported(); | 1161 return Status::ErrorUnsupported(); |
1171 } | |
1172 | 1162 |
1173 HASHContext* context = HASH_Create(hash_type); | 1163 HASHContext* context = HASH_Create(hash_type); |
1174 if (!context) { | 1164 if (!context) |
1175 return Status::Error(); | 1165 return Status::Error(); |
1176 } | |
1177 | 1166 |
1178 HASH_Begin(context); | 1167 HASH_Begin(context); |
1179 | 1168 |
1180 HASH_Update(context, data, data_size); | 1169 HASH_Update(context, data, data_size); |
1181 | 1170 |
1182 unsigned hash_result_length = HASH_ResultLenContext(context); | 1171 unsigned hash_result_length = HASH_ResultLenContext(context); |
1183 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); | 1172 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); |
1184 | 1173 |
1185 *buffer = blink::WebArrayBuffer::create(hash_result_length, 1); | 1174 *buffer = blink::WebArrayBuffer::create(hash_result_length, 1); |
1186 | 1175 |
1187 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); | 1176 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); |
1188 | 1177 |
1189 unsigned result_length = 0; | 1178 unsigned result_length = 0; |
1190 HASH_End(context, digest, &result_length, hash_result_length); | 1179 HASH_End(context, digest, &result_length, hash_result_length); |
1191 | 1180 |
1192 HASH_Destroy(context); | 1181 HASH_Destroy(context); |
1193 | 1182 |
1194 if (result_length != hash_result_length) { | 1183 if (result_length != hash_result_length) |
1195 return Status::ErrorUnexpected(); | 1184 return Status::ErrorUnexpected(); |
1196 } | |
1197 return Status::Success(); | 1185 return Status::Success(); |
1198 } | 1186 } |
1199 | 1187 |
1200 Status WebCryptoImpl::GenerateSecretKeyInternal( | 1188 Status WebCryptoImpl::GenerateSecretKeyInternal( |
1201 const blink::WebCryptoAlgorithm& algorithm, | 1189 const blink::WebCryptoAlgorithm& algorithm, |
1202 bool extractable, | 1190 bool extractable, |
1203 blink::WebCryptoKeyUsageMask usage_mask, | 1191 blink::WebCryptoKeyUsageMask usage_mask, |
1204 blink::WebCryptoKey* key) { | 1192 blink::WebCryptoKey* key) { |
1205 | 1193 |
1206 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm); | 1194 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm); |
1207 blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret; | 1195 blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret; |
1208 | 1196 |
1209 if (mech == CKM_INVALID_MECHANISM) { | 1197 if (mech == CKM_INVALID_MECHANISM) |
1210 return Status::ErrorUnsupported(); | 1198 return Status::ErrorUnsupported(); |
1211 } | |
1212 | 1199 |
1213 unsigned int keylen_bytes = 0; | 1200 unsigned int keylen_bytes = 0; |
1214 Status status = GetGenerateSecretKeyLength(algorithm, &keylen_bytes); | 1201 Status status = GetGenerateSecretKeyLength(algorithm, &keylen_bytes); |
1215 if (status.IsError()) | 1202 if (status.IsError()) |
1216 return status; | 1203 return status; |
1217 | 1204 |
1218 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); | 1205 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
1219 if (!slot) { | 1206 if (!slot) |
1220 return Status::Error(); | 1207 return Status::Error(); |
1221 } | |
1222 | 1208 |
1223 crypto::ScopedPK11SymKey pk11_key( | 1209 crypto::ScopedPK11SymKey pk11_key( |
1224 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); | 1210 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); |
1225 | 1211 |
1226 if (!pk11_key) { | 1212 if (!pk11_key) |
1227 return Status::Error(); | 1213 return Status::Error(); |
1228 } | |
1229 | 1214 |
1230 *key = blink::WebCryptoKey::create( | 1215 *key = blink::WebCryptoKey::create( |
1231 new SymKeyHandle(pk11_key.Pass()), | 1216 new SymKeyHandle(pk11_key.Pass()), |
1232 key_type, extractable, algorithm, usage_mask); | 1217 key_type, extractable, algorithm, usage_mask); |
1233 return Status::Success(); | 1218 return Status::Success(); |
1234 } | 1219 } |
1235 | 1220 |
1236 Status WebCryptoImpl::GenerateKeyPairInternal( | 1221 Status WebCryptoImpl::GenerateKeyPairInternal( |
1237 const blink::WebCryptoAlgorithm& algorithm, | 1222 const blink::WebCryptoAlgorithm& algorithm, |
1238 bool extractable, | 1223 bool extractable, |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1418 | 1403 |
1419 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), | 1404 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), |
1420 blink::WebCryptoKeyTypePublic, | 1405 blink::WebCryptoKeyTypePublic, |
1421 extractable, | 1406 extractable, |
1422 algorithm, | 1407 algorithm, |
1423 usage_mask); | 1408 usage_mask); |
1424 return Status::Success(); | 1409 return Status::Success(); |
1425 } | 1410 } |
1426 | 1411 |
1427 } // namespace content | 1412 } // namespace content |
OLD | NEW |