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