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 switch (algorithm.id()) { | |
86 case blink::WebCryptoAlgorithmIdSha1: | |
87 return SEC_OID_SHA1; | |
88 case blink::WebCryptoAlgorithmIdSha224: | |
89 return SEC_OID_SHA224; | |
90 case blink::WebCryptoAlgorithmIdSha256: | |
91 return SEC_OID_SHA256; | |
92 case blink::WebCryptoAlgorithmIdSha384: | |
93 return SEC_OID_SHA384; | |
94 case blink::WebCryptoAlgorithmIdSha512: | |
95 return SEC_OID_SHA512; | |
96 default: | |
97 return SEC_OID_UNKNOWN; | |
98 } | |
99 } | |
100 | |
83 CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism( | 101 CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism( |
84 const blink::WebCryptoAlgorithm& algorithm) { | 102 const blink::WebCryptoAlgorithm& algorithm) { |
85 switch (algorithm.id()) { | 103 switch (algorithm.id()) { |
86 case blink::WebCryptoAlgorithmIdSha1: | 104 case blink::WebCryptoAlgorithmIdSha1: |
87 return CKM_SHA_1_HMAC; | 105 return CKM_SHA_1_HMAC; |
88 case blink::WebCryptoAlgorithmIdSha256: | 106 case blink::WebCryptoAlgorithmIdSha256: |
89 return CKM_SHA256_HMAC; | 107 return CKM_SHA256_HMAC; |
90 default: | 108 default: |
91 // Not a supported algorithm. | 109 // Not a supported algorithm. |
92 return CKM_INVALID_MECHANISM; | 110 return CKM_INVALID_MECHANISM; |
(...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
854 return false; | 872 return false; |
855 } | 873 } |
856 } | 874 } |
857 | 875 |
858 bool WebCryptoImpl::SignInternal( | 876 bool WebCryptoImpl::SignInternal( |
859 const blink::WebCryptoAlgorithm& algorithm, | 877 const blink::WebCryptoAlgorithm& algorithm, |
860 const blink::WebCryptoKey& key, | 878 const blink::WebCryptoKey& key, |
861 const unsigned char* data, | 879 const unsigned char* data, |
862 unsigned data_size, | 880 unsigned data_size, |
863 blink::WebArrayBuffer* buffer) { | 881 blink::WebArrayBuffer* buffer) { |
882 | |
883 // Note: It is not an error to sign empty data. | |
884 | |
885 DCHECK(buffer); | |
886 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); | |
887 | |
864 blink::WebArrayBuffer result; | 888 blink::WebArrayBuffer result; |
865 | 889 |
866 switch (algorithm.id()) { | 890 switch (algorithm.id()) { |
867 case blink::WebCryptoAlgorithmIdHmac: { | 891 case blink::WebCryptoAlgorithmIdHmac: { |
868 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); | 892 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
869 if (!params) { | 893 if (!params) { |
870 return false; | 894 return false; |
871 } | 895 } |
872 | 896 |
873 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 897 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
874 | 898 |
875 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), | 899 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), |
876 WebCryptoAlgorithmToHMACMechanism(params->hash())); | 900 WebCryptoAlgorithmToHMACMechanism(params->hash())); |
877 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); | |
878 | 901 |
879 SECItem param_item = { siBuffer, NULL, 0 }; | 902 SECItem param_item = { siBuffer, NULL, 0 }; |
880 SECItem data_item = { | 903 SECItem data_item = { |
881 siBuffer, | 904 siBuffer, |
882 const_cast<unsigned char*>(data), | 905 const_cast<unsigned char*>(data), |
883 data_size | 906 data_size |
884 }; | 907 }; |
885 // First call is to figure out the length. | 908 // First call is to figure out the length. |
886 SECItem signature_item = { siBuffer, NULL, 0 }; | 909 SECItem signature_item = { siBuffer, NULL, 0 }; |
887 | 910 |
(...skipping 17 matching lines...) Expand all Loading... | |
905 &signature_item, | 928 &signature_item, |
906 &data_item) != SECSuccess) { | 929 &data_item) != SECSuccess) { |
907 NOTREACHED(); | 930 NOTREACHED(); |
908 return false; | 931 return false; |
909 } | 932 } |
910 | 933 |
911 DCHECK_EQ(result.byteLength(), signature_item.len); | 934 DCHECK_EQ(result.byteLength(), signature_item.len); |
912 | 935 |
913 break; | 936 break; |
914 } | 937 } |
938 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { | |
939 // Only private key signing is supported. | |
940 if (key.type() != blink::WebCryptoKeyTypePrivate) | |
941 return false; | |
942 | |
943 PrivateKeyHandle* const private_key = | |
944 reinterpret_cast<PrivateKeyHandle*>(key.handle()); | |
945 DCHECK(private_key); | |
946 DCHECK(private_key->key()); | |
947 | |
948 // Get the inner hash algorithm and convert to an NSS SECOidTag | |
949 const blink::WebCryptoAlgorithm hash_algorithm = | |
950 webcrypto::GetInnerHashAlgorithm(algorithm); | |
951 if (hash_algorithm.isNull()) // TODO(padolph): DCHECK instead? | |
952 return false; | |
953 const SECOidTag hash_alg_tag = | |
954 WebCryptoAlgorithmToNssSecOidShaTag(hash_algorithm); | |
955 if (hash_alg_tag == SEC_OID_UNKNOWN) | |
956 return false; | |
957 | |
958 // Get the NSS signature algorithm SECOidTag corresponding to the key type | |
959 // and inner hash algorithm SECOidTag. | |
960 const SECOidTag sign_alg_tag = SEC_GetSignatureAlgorithmOidTag( | |
961 private_key->key()->keyType, | |
962 hash_alg_tag); | |
963 if (sign_alg_tag == SEC_OID_UNKNOWN) | |
964 return false; | |
965 | |
966 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0)); | |
967 if (SEC_SignData(signature_item.get(), | |
968 data, | |
969 data_size, | |
970 private_key->key(), | |
971 sign_alg_tag) != SECSuccess) { | |
972 return false; | |
973 } | |
974 | |
975 result = webcrypto::CreateArrayBuffer(signature_item->data, | |
976 signature_item->len); | |
977 | |
978 break; | |
979 } | |
915 default: | 980 default: |
916 return false; | 981 return false; |
917 } | 982 } |
918 | 983 |
919 *buffer = result; | 984 *buffer = result; |
920 return true; | 985 return true; |
921 } | 986 } |
922 | 987 |
923 bool WebCryptoImpl::VerifySignatureInternal( | 988 bool WebCryptoImpl::VerifySignatureInternal( |
924 const blink::WebCryptoAlgorithm& algorithm, | 989 const blink::WebCryptoAlgorithm& algorithm, |
925 const blink::WebCryptoKey& key, | 990 const blink::WebCryptoKey& key, |
926 const unsigned char* signature, | 991 const unsigned char* signature, |
927 unsigned signature_size, | 992 unsigned signature_size, |
928 const unsigned char* data, | 993 const unsigned char* data, |
929 unsigned data_size, | 994 unsigned data_size, |
930 bool* signature_match) { | 995 bool* signature_match) { |
996 | |
997 if (!signature_size) | |
998 return false; | |
999 DCHECK(signature); | |
1000 | |
931 switch (algorithm.id()) { | 1001 switch (algorithm.id()) { |
932 case blink::WebCryptoAlgorithmIdHmac: { | 1002 case blink::WebCryptoAlgorithmIdHmac: { |
933 blink::WebArrayBuffer result; | 1003 blink::WebArrayBuffer result; |
934 if (!SignInternal(algorithm, key, data, data_size, &result)) { | 1004 if (!SignInternal(algorithm, key, data, data_size, &result)) { |
935 return false; | 1005 return false; |
936 } | 1006 } |
937 | 1007 |
938 // Handling of truncated signatures is underspecified in the WebCrypto | 1008 // Handling of truncated signatures is underspecified in the WebCrypto |
939 // spec, so here we fail verification if a truncated signature is being | 1009 // spec, so here we fail verification if a truncated signature is being |
940 // verified. | 1010 // verified. |
941 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 | 1011 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 |
942 *signature_match = | 1012 *signature_match = |
943 result.byteLength() == signature_size && | 1013 result.byteLength() == signature_size && |
944 crypto::SecureMemEqual(result.data(), signature, signature_size); | 1014 crypto::SecureMemEqual(result.data(), signature, signature_size); |
945 | 1015 |
946 break; | 1016 break; |
947 } | 1017 } |
1018 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { | |
1019 | |
1020 // Only public key signature verification is supported. | |
1021 if (key.type() != blink::WebCryptoKeyTypePublic) | |
1022 return false; | |
1023 | |
1024 PublicKeyHandle* const public_key = | |
1025 reinterpret_cast<PublicKeyHandle*>(key.handle()); | |
1026 DCHECK(public_key); | |
1027 DCHECK(public_key->key()); | |
1028 | |
1029 const SECItem signature_item = { | |
1030 siBuffer, | |
1031 const_cast<unsigned char*>(signature), | |
1032 signature_size | |
1033 }; | |
1034 | |
1035 const SECOidTag hash_alg_tag = WebCryptoAlgorithmToNssSecOidShaTag( | |
eroman
2013/12/19 22:56:38
Please check for SEC_OID_UNKNOWN and fail.
Passin
padolph
2013/12/20 00:03:39
Done.
| |
1036 webcrypto::GetInnerHashAlgorithm(algorithm)); | |
1037 | |
1038 *signature_match = | |
1039 VFY_VerifyDataDirect( | |
1040 data, | |
1041 data_size, | |
1042 public_key->key(), | |
1043 &signature_item, | |
1044 SEC_OID_PKCS1_RSA_ENCRYPTION, | |
1045 hash_alg_tag, | |
1046 NULL, | |
1047 NULL) == SECSuccess; | |
1048 | |
1049 break; | |
1050 } | |
948 default: | 1051 default: |
949 return false; | 1052 return false; |
950 } | 1053 } |
951 | 1054 |
952 return true; | 1055 return true; |
953 } | 1056 } |
954 | 1057 |
955 bool WebCryptoImpl::ImportRsaPublicKeyInternal( | 1058 bool WebCryptoImpl::ImportRsaPublicKeyInternal( |
956 const unsigned char* modulus_data, | 1059 const unsigned char* modulus_data, |
957 unsigned modulus_size, | 1060 unsigned modulus_size, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1004 | 1107 |
1005 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), | 1108 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), |
1006 blink::WebCryptoKeyTypePublic, | 1109 blink::WebCryptoKeyTypePublic, |
1007 extractable, | 1110 extractable, |
1008 algorithm, | 1111 algorithm, |
1009 usage_mask); | 1112 usage_mask); |
1010 return true; | 1113 return true; |
1011 } | 1114 } |
1012 | 1115 |
1013 } // namespace content | 1116 } // namespace content |
OLD | NEW |