Chromium Code Reviews| 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 case blink::WebCryptoAlgorithmIdSha384: | 73 case blink::WebCryptoAlgorithmIdSha384: |
| 74 return HASH_AlgSHA384; | 74 return HASH_AlgSHA384; |
| 75 case blink::WebCryptoAlgorithmIdSha512: | 75 case blink::WebCryptoAlgorithmIdSha512: |
| 76 return HASH_AlgSHA512; | 76 return HASH_AlgSHA512; |
| 77 default: | 77 default: |
| 78 // Not a digest algorithm. | 78 // Not a digest algorithm. |
| 79 return HASH_AlgNULL; | 79 return HASH_AlgNULL; |
| 80 } | 80 } |
| 81 } | 81 } |
| 82 | 82 |
| 83 SECOidTag WebCryptoAlgorithmToNssSecOidShaTag( | |
| 84 const blink::WebCryptoAlgorithm& algorithm) { | |
| 85 DCHECK(!algorithm.isNull()); | |
| 86 switch (algorithm.id()) { | |
| 87 case blink::WebCryptoAlgorithmIdSha1: | |
| 88 return SEC_OID_SHA1; | |
| 89 case blink::WebCryptoAlgorithmIdSha224: | |
| 90 return SEC_OID_SHA224; | |
| 91 case blink::WebCryptoAlgorithmIdSha256: | |
| 92 return SEC_OID_SHA256; | |
| 93 case blink::WebCryptoAlgorithmIdSha384: | |
| 94 return SEC_OID_SHA384; | |
| 95 case blink::WebCryptoAlgorithmIdSha512: | |
| 96 return SEC_OID_SHA512; | |
| 97 default: | |
| 98 return SEC_OID_UNKNOWN; | |
| 99 } | |
| 100 } | |
| 101 | |
| 83 CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism( | 102 CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism( |
| 84 const blink::WebCryptoAlgorithm& algorithm) { | 103 const blink::WebCryptoAlgorithm& algorithm) { |
| 85 switch (algorithm.id()) { | 104 switch (algorithm.id()) { |
| 86 case blink::WebCryptoAlgorithmIdSha1: | 105 case blink::WebCryptoAlgorithmIdSha1: |
| 87 return CKM_SHA_1_HMAC; | 106 return CKM_SHA_1_HMAC; |
| 88 case blink::WebCryptoAlgorithmIdSha256: | 107 case blink::WebCryptoAlgorithmIdSha256: |
| 89 return CKM_SHA256_HMAC; | 108 return CKM_SHA256_HMAC; |
| 90 default: | 109 default: |
| 91 // Not a supported algorithm. | 110 // Not a supported algorithm. |
| 92 return CKM_INVALID_MECHANISM; | 111 return CKM_INVALID_MECHANISM; |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 261 case blink::WebCryptoAlgorithmIdHmac: | 280 case blink::WebCryptoAlgorithmIdHmac: |
| 262 case blink::WebCryptoAlgorithmIdAesCbc: | 281 case blink::WebCryptoAlgorithmIdAesCbc: |
| 263 case blink::WebCryptoAlgorithmIdAesKw: | 282 case blink::WebCryptoAlgorithmIdAesKw: |
| 264 type = blink::WebCryptoKeyTypeSecret; | 283 type = blink::WebCryptoKeyTypeSecret; |
| 265 break; | 284 break; |
| 266 // TODO(bryaneyler): Support more key types. | 285 // TODO(bryaneyler): Support more key types. |
| 267 default: | 286 default: |
| 268 return false; | 287 return false; |
| 269 } | 288 } |
| 270 | 289 |
| 290 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. | |
| 291 // Currently only supporting symmetric. | |
| 271 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; | 292 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; |
| 272 // Flags are verified at the Blink layer; here the flags are set to all | 293 // Flags are verified at the Blink layer; here the flags are set to all |
| 273 // possible operations for this key type. | 294 // possible operations for this key type. |
| 274 CK_FLAGS flags = 0; | 295 CK_FLAGS flags = 0; |
| 275 | 296 |
| 276 switch (algorithm.id()) { | 297 switch (algorithm.id()) { |
| 277 case blink::WebCryptoAlgorithmIdHmac: { | 298 case blink::WebCryptoAlgorithmIdHmac: { |
| 278 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); | 299 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
| 279 if (!params) { | 300 if (!params) { |
| 280 return false; | 301 return false; |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 861 return false; | 882 return false; |
| 862 } | 883 } |
| 863 } | 884 } |
| 864 | 885 |
| 865 bool WebCryptoImpl::SignInternal( | 886 bool WebCryptoImpl::SignInternal( |
| 866 const blink::WebCryptoAlgorithm& algorithm, | 887 const blink::WebCryptoAlgorithm& algorithm, |
| 867 const blink::WebCryptoKey& key, | 888 const blink::WebCryptoKey& key, |
| 868 const unsigned char* data, | 889 const unsigned char* data, |
| 869 unsigned data_size, | 890 unsigned data_size, |
| 870 blink::WebArrayBuffer* buffer) { | 891 blink::WebArrayBuffer* buffer) { |
| 892 | |
| 893 // Note: It is not an error to sign empty data. | |
| 894 | |
| 895 DCHECK(buffer); | |
| 896 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); | |
| 897 | |
| 871 blink::WebArrayBuffer result; | 898 blink::WebArrayBuffer result; |
| 872 | 899 |
| 873 switch (algorithm.id()) { | 900 switch (algorithm.id()) { |
| 874 case blink::WebCryptoAlgorithmIdHmac: { | 901 case blink::WebCryptoAlgorithmIdHmac: { |
| 875 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); | 902 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
| 876 if (!params) { | 903 if (!params) { |
| 877 return false; | 904 return false; |
| 878 } | 905 } |
| 879 | 906 |
| 880 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 907 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
| 881 | 908 |
| 882 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), | 909 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), |
| 883 WebCryptoAlgorithmToHMACMechanism(params->hash())); | 910 WebCryptoAlgorithmToHMACMechanism(params->hash())); |
| 884 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); | |
| 885 | 911 |
| 886 SECItem param_item = { siBuffer, NULL, 0 }; | 912 SECItem param_item = { siBuffer, NULL, 0 }; |
| 887 SECItem data_item = { | 913 SECItem data_item = { |
| 888 siBuffer, | 914 siBuffer, |
| 889 const_cast<unsigned char*>(data), | 915 const_cast<unsigned char*>(data), |
| 890 data_size | 916 data_size |
| 891 }; | 917 }; |
| 892 // First call is to figure out the length. | 918 // First call is to figure out the length. |
| 893 SECItem signature_item = { siBuffer, NULL, 0 }; | 919 SECItem signature_item = { siBuffer, NULL, 0 }; |
| 894 | 920 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 912 &signature_item, | 938 &signature_item, |
| 913 &data_item) != SECSuccess) { | 939 &data_item) != SECSuccess) { |
| 914 NOTREACHED(); | 940 NOTREACHED(); |
| 915 return false; | 941 return false; |
| 916 } | 942 } |
| 917 | 943 |
| 918 DCHECK_EQ(result.byteLength(), signature_item.len); | 944 DCHECK_EQ(result.byteLength(), signature_item.len); |
| 919 | 945 |
| 920 break; | 946 break; |
| 921 } | 947 } |
| 948 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { | |
| 949 // Only private key signing is supported. | |
| 950 if (key.type() != blink::WebCryptoKeyTypePrivate) | |
| 951 return false; | |
| 952 | |
| 953 PrivateKeyHandle* const private_key = | |
| 954 reinterpret_cast<PrivateKeyHandle*>(key.handle()); | |
| 955 DCHECK(private_key); | |
| 956 DCHECK(private_key->key()); | |
| 957 | |
| 958 // Get the inner hash algorithm and convert to an NSS SECOidTag | |
| 959 const blink::WebCryptoAlgorithm hash_algorithm = | |
| 960 webcrypto::GetInnerHashAlgorithm(algorithm); | |
| 961 if (hash_algorithm.isNull()) // TODO(padolph): DCHECK instead? | |
| 962 return false; | |
| 963 const SECOidTag hash_alg_tag = | |
| 964 WebCryptoAlgorithmToNssSecOidShaTag(hash_algorithm); | |
| 965 if (hash_alg_tag == SEC_OID_UNKNOWN) | |
| 966 return false; | |
| 967 | |
| 968 // Get the NSS signature algorithm SECOidTag corresponding to the key type | |
| 969 // and inner hash algorithm SECOidTag. | |
| 970 const SECOidTag sign_alg_tag = SEC_GetSignatureAlgorithmOidTag( | |
| 971 private_key->key()->keyType, | |
| 972 hash_alg_tag); | |
|
Ryan Sleevi
2013/12/20 02:08:50
This is unnecessary. The design of this API was me
padolph
2013/12/21 02:44:17
Done.
| |
| 973 if (sign_alg_tag == SEC_OID_UNKNOWN) | |
| 974 return false; | |
| 975 | |
| 976 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0)); | |
| 977 if (SEC_SignData(signature_item.get(), | |
| 978 data, | |
| 979 data_size, | |
| 980 private_key->key(), | |
| 981 sign_alg_tag) != SECSuccess) { | |
| 982 return false; | |
| 983 } | |
| 984 | |
| 985 result = webcrypto::CreateArrayBuffer(signature_item->data, | |
| 986 signature_item->len); | |
| 987 | |
| 988 break; | |
| 989 } | |
| 922 default: | 990 default: |
| 923 return false; | 991 return false; |
| 924 } | 992 } |
| 925 | 993 |
| 926 *buffer = result; | 994 *buffer = result; |
| 927 return true; | 995 return true; |
| 928 } | 996 } |
| 929 | 997 |
| 930 bool WebCryptoImpl::VerifySignatureInternal( | 998 bool WebCryptoImpl::VerifySignatureInternal( |
| 931 const blink::WebCryptoAlgorithm& algorithm, | 999 const blink::WebCryptoAlgorithm& algorithm, |
| 932 const blink::WebCryptoKey& key, | 1000 const blink::WebCryptoKey& key, |
| 933 const unsigned char* signature, | 1001 const unsigned char* signature, |
| 934 unsigned signature_size, | 1002 unsigned signature_size, |
| 935 const unsigned char* data, | 1003 const unsigned char* data, |
| 936 unsigned data_size, | 1004 unsigned data_size, |
| 937 bool* signature_match) { | 1005 bool* signature_match) { |
| 1006 | |
| 1007 if (!signature_size) | |
| 1008 return false; | |
| 1009 DCHECK(signature); | |
| 1010 | |
| 938 switch (algorithm.id()) { | 1011 switch (algorithm.id()) { |
| 939 case blink::WebCryptoAlgorithmIdHmac: { | 1012 case blink::WebCryptoAlgorithmIdHmac: { |
| 940 blink::WebArrayBuffer result; | 1013 blink::WebArrayBuffer result; |
| 941 if (!SignInternal(algorithm, key, data, data_size, &result)) { | 1014 if (!SignInternal(algorithm, key, data, data_size, &result)) { |
| 942 return false; | 1015 return false; |
| 943 } | 1016 } |
| 944 | 1017 |
| 945 // Handling of truncated signatures is underspecified in the WebCrypto | 1018 // Handling of truncated signatures is underspecified in the WebCrypto |
| 946 // spec, so here we fail verification if a truncated signature is being | 1019 // spec, so here we fail verification if a truncated signature is being |
| 947 // verified. | 1020 // verified. |
| 948 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 | 1021 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 |
| 949 *signature_match = | 1022 *signature_match = |
| 950 result.byteLength() == signature_size && | 1023 result.byteLength() == signature_size && |
| 951 crypto::SecureMemEqual(result.data(), signature, signature_size); | 1024 crypto::SecureMemEqual(result.data(), signature, signature_size); |
| 952 | 1025 |
| 953 break; | 1026 break; |
| 954 } | 1027 } |
| 1028 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { | |
| 1029 | |
|
Ryan Sleevi
2013/12/20 02:08:50
unnecessary newline
padolph
2013/12/21 02:44:17
Done.
| |
| 1030 // Only public key signature verification is supported. | |
|
Ryan Sleevi
2013/12/20 02:08:50
This comment makes no sense, given the algorithm b
padolph
2013/12/21 02:44:17
Done.
| |
| 1031 if (key.type() != blink::WebCryptoKeyTypePublic) | |
| 1032 return false; | |
| 1033 | |
| 1034 PublicKeyHandle* const public_key = | |
| 1035 reinterpret_cast<PublicKeyHandle*>(key.handle()); | |
| 1036 DCHECK(public_key); | |
| 1037 DCHECK(public_key->key()); | |
| 1038 | |
| 1039 const SECItem signature_item = { | |
| 1040 siBuffer, | |
| 1041 const_cast<unsigned char*>(signature), | |
| 1042 signature_size | |
| 1043 }; | |
| 1044 | |
| 1045 const SECOidTag hash_alg_tag = WebCryptoAlgorithmToNssSecOidShaTag( | |
| 1046 webcrypto::GetInnerHashAlgorithm(algorithm)); | |
| 1047 if (hash_alg_tag == SEC_OID_UNKNOWN) | |
| 1048 return false; | |
| 1049 | |
| 1050 *signature_match = | |
| 1051 VFY_VerifyDataDirect( | |
| 1052 data, | |
| 1053 data_size, | |
| 1054 public_key->key(), | |
| 1055 &signature_item, | |
| 1056 SEC_OID_PKCS1_RSA_ENCRYPTION, | |
| 1057 hash_alg_tag, | |
| 1058 NULL, | |
| 1059 NULL) == SECSuccess; | |
|
Ryan Sleevi
2013/12/20 02:08:50
Was this run through git cl format? The formatting
padolph
2013/12/21 02:44:17
Rewrote yoda style and reformatted, and ran throug
| |
| 1060 | |
| 1061 break; | |
| 1062 } | |
| 955 default: | 1063 default: |
| 956 return false; | 1064 return false; |
| 957 } | 1065 } |
| 958 | 1066 |
| 959 return true; | 1067 return true; |
| 960 } | 1068 } |
| 961 | 1069 |
| 962 bool WebCryptoImpl::ImportRsaPublicKeyInternal( | 1070 bool WebCryptoImpl::ImportRsaPublicKeyInternal( |
| 963 const unsigned char* modulus_data, | 1071 const unsigned char* modulus_data, |
| 964 unsigned modulus_size, | 1072 unsigned modulus_size, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1011 | 1119 |
| 1012 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), | 1120 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), |
| 1013 blink::WebCryptoKeyTypePublic, | 1121 blink::WebCryptoKeyTypePublic, |
| 1014 extractable, | 1122 extractable, |
| 1015 algorithm, | 1123 algorithm, |
| 1016 usage_mask); | 1124 usage_mask); |
| 1017 return true; | 1125 return true; |
| 1018 } | 1126 } |
| 1019 | 1127 |
| 1020 } // namespace content | 1128 } // namespace content |
| OLD | NEW |