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 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 case blink::WebCryptoAlgorithmIdHmac: | 238 case blink::WebCryptoAlgorithmIdHmac: |
239 case blink::WebCryptoAlgorithmIdAesCbc: | 239 case blink::WebCryptoAlgorithmIdAesCbc: |
240 case blink::WebCryptoAlgorithmIdAesKw: | 240 case blink::WebCryptoAlgorithmIdAesKw: |
241 type = blink::WebCryptoKeyTypeSecret; | 241 type = blink::WebCryptoKeyTypeSecret; |
242 break; | 242 break; |
243 // TODO(bryaneyler): Support more key types. | 243 // TODO(bryaneyler): Support more key types. |
244 default: | 244 default: |
245 return false; | 245 return false; |
246 } | 246 } |
247 | 247 |
| 248 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. |
| 249 // Currently only supporting symmetric. |
248 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; | 250 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; |
249 // Flags are verified at the Blink layer; here the flags are set to all | 251 // Flags are verified at the Blink layer; here the flags are set to all |
250 // possible operations for this key type. | 252 // possible operations for this key type. |
251 CK_FLAGS flags = 0; | 253 CK_FLAGS flags = 0; |
252 | 254 |
253 switch (algorithm.id()) { | 255 switch (algorithm.id()) { |
254 case blink::WebCryptoAlgorithmIdHmac: { | 256 case blink::WebCryptoAlgorithmIdHmac: { |
255 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); | 257 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
256 if (!params) { | 258 if (!params) { |
257 return false; | 259 return false; |
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 return false; | 844 return false; |
843 } | 845 } |
844 } | 846 } |
845 | 847 |
846 bool WebCryptoImpl::SignInternal( | 848 bool WebCryptoImpl::SignInternal( |
847 const blink::WebCryptoAlgorithm& algorithm, | 849 const blink::WebCryptoAlgorithm& algorithm, |
848 const blink::WebCryptoKey& key, | 850 const blink::WebCryptoKey& key, |
849 const unsigned char* data, | 851 const unsigned char* data, |
850 unsigned data_size, | 852 unsigned data_size, |
851 blink::WebArrayBuffer* buffer) { | 853 blink::WebArrayBuffer* buffer) { |
| 854 |
| 855 // Note: It is not an error to sign empty data. |
| 856 |
| 857 DCHECK(buffer); |
| 858 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); |
| 859 |
852 blink::WebArrayBuffer result; | 860 blink::WebArrayBuffer result; |
853 | 861 |
854 switch (algorithm.id()) { | 862 switch (algorithm.id()) { |
855 case blink::WebCryptoAlgorithmIdHmac: { | 863 case blink::WebCryptoAlgorithmIdHmac: { |
856 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); | 864 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
857 if (!params) { | 865 if (!params) { |
858 return false; | 866 return false; |
859 } | 867 } |
860 | 868 |
861 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 869 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
862 | 870 |
863 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), | 871 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), |
864 WebCryptoHashToHMACMechanism(params->hash())); | 872 WebCryptoHashToHMACMechanism(params->hash())); |
865 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); | |
866 | 873 |
867 SECItem param_item = { siBuffer, NULL, 0 }; | 874 SECItem param_item = { siBuffer, NULL, 0 }; |
868 SECItem data_item = { | 875 SECItem data_item = { |
869 siBuffer, | 876 siBuffer, |
870 const_cast<unsigned char*>(data), | 877 const_cast<unsigned char*>(data), |
871 data_size | 878 data_size |
872 }; | 879 }; |
873 // First call is to figure out the length. | 880 // First call is to figure out the length. |
874 SECItem signature_item = { siBuffer, NULL, 0 }; | 881 SECItem signature_item = { siBuffer, NULL, 0 }; |
875 | 882 |
(...skipping 17 matching lines...) Expand all Loading... |
893 &signature_item, | 900 &signature_item, |
894 &data_item) != SECSuccess) { | 901 &data_item) != SECSuccess) { |
895 NOTREACHED(); | 902 NOTREACHED(); |
896 return false; | 903 return false; |
897 } | 904 } |
898 | 905 |
899 DCHECK_EQ(result.byteLength(), signature_item.len); | 906 DCHECK_EQ(result.byteLength(), signature_item.len); |
900 | 907 |
901 break; | 908 break; |
902 } | 909 } |
| 910 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { |
| 911 if (key.type() != blink::WebCryptoKeyTypePrivate || |
| 912 webcrypto::GetInnerHashAlgorithm(algorithm).isNull()) |
| 913 return false; |
| 914 |
| 915 PrivateKeyHandle* const private_key = |
| 916 reinterpret_cast<PrivateKeyHandle*>(key.handle()); |
| 917 DCHECK(private_key); |
| 918 DCHECK(private_key->key()); |
| 919 |
| 920 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the |
| 921 // inner hash of the input Web Crypto algorithm. |
| 922 SECOidTag sign_alg_tag; |
| 923 switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) { |
| 924 case blink::WebCryptoAlgorithmIdSha1: |
| 925 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
| 926 break; |
| 927 case blink::WebCryptoAlgorithmIdSha224: |
| 928 sign_alg_tag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION; |
| 929 break; |
| 930 case blink::WebCryptoAlgorithmIdSha256: |
| 931 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
| 932 break; |
| 933 case blink::WebCryptoAlgorithmIdSha384: |
| 934 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; |
| 935 break; |
| 936 case blink::WebCryptoAlgorithmIdSha512: |
| 937 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; |
| 938 break; |
| 939 default: |
| 940 return false; |
| 941 } |
| 942 |
| 943 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0)); |
| 944 if (SEC_SignData(signature_item.get(), |
| 945 data, |
| 946 data_size, |
| 947 private_key->key(), |
| 948 sign_alg_tag) != SECSuccess) { |
| 949 return false; |
| 950 } |
| 951 |
| 952 result = webcrypto::CreateArrayBuffer(signature_item->data, |
| 953 signature_item->len); |
| 954 |
| 955 break; |
| 956 } |
903 default: | 957 default: |
904 return false; | 958 return false; |
905 } | 959 } |
906 | 960 |
907 *buffer = result; | 961 *buffer = result; |
908 return true; | 962 return true; |
909 } | 963 } |
910 | 964 |
911 bool WebCryptoImpl::VerifySignatureInternal( | 965 bool WebCryptoImpl::VerifySignatureInternal( |
912 const blink::WebCryptoAlgorithm& algorithm, | 966 const blink::WebCryptoAlgorithm& algorithm, |
913 const blink::WebCryptoKey& key, | 967 const blink::WebCryptoKey& key, |
914 const unsigned char* signature, | 968 const unsigned char* signature, |
915 unsigned signature_size, | 969 unsigned signature_size, |
916 const unsigned char* data, | 970 const unsigned char* data, |
917 unsigned data_size, | 971 unsigned data_size, |
918 bool* signature_match) { | 972 bool* signature_match) { |
| 973 |
| 974 if (!signature_size) |
| 975 return false; |
| 976 DCHECK(signature); |
| 977 |
919 switch (algorithm.id()) { | 978 switch (algorithm.id()) { |
920 case blink::WebCryptoAlgorithmIdHmac: { | 979 case blink::WebCryptoAlgorithmIdHmac: { |
921 blink::WebArrayBuffer result; | 980 blink::WebArrayBuffer result; |
922 if (!SignInternal(algorithm, key, data, data_size, &result)) { | 981 if (!SignInternal(algorithm, key, data, data_size, &result)) { |
923 return false; | 982 return false; |
924 } | 983 } |
925 | 984 |
926 // Handling of truncated signatures is underspecified in the WebCrypto | 985 // Handling of truncated signatures is underspecified in the WebCrypto |
927 // spec, so here we fail verification if a truncated signature is being | 986 // spec, so here we fail verification if a truncated signature is being |
928 // verified. | 987 // verified. |
929 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 | 988 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 |
930 *signature_match = | 989 *signature_match = |
931 result.byteLength() == signature_size && | 990 result.byteLength() == signature_size && |
932 crypto::SecureMemEqual(result.data(), signature, signature_size); | 991 crypto::SecureMemEqual(result.data(), signature, signature_size); |
933 | 992 |
934 break; | 993 break; |
935 } | 994 } |
| 995 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { |
| 996 if (key.type() != blink::WebCryptoKeyTypePublic) |
| 997 return false; |
| 998 |
| 999 PublicKeyHandle* const public_key = |
| 1000 reinterpret_cast<PublicKeyHandle*>(key.handle()); |
| 1001 DCHECK(public_key); |
| 1002 DCHECK(public_key->key()); |
| 1003 |
| 1004 const SECItem signature_item = { |
| 1005 siBuffer, |
| 1006 const_cast<unsigned char*>(signature), |
| 1007 signature_size |
| 1008 }; |
| 1009 |
| 1010 SECOidTag hash_alg_tag; |
| 1011 switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) { |
| 1012 case blink::WebCryptoAlgorithmIdSha1: |
| 1013 hash_alg_tag = SEC_OID_SHA1; |
| 1014 break; |
| 1015 case blink::WebCryptoAlgorithmIdSha224: |
| 1016 hash_alg_tag = SEC_OID_SHA224; |
| 1017 break; |
| 1018 case blink::WebCryptoAlgorithmIdSha256: |
| 1019 hash_alg_tag = SEC_OID_SHA256; |
| 1020 break; |
| 1021 case blink::WebCryptoAlgorithmIdSha384: |
| 1022 hash_alg_tag = SEC_OID_SHA384; |
| 1023 break; |
| 1024 case blink::WebCryptoAlgorithmIdSha512: |
| 1025 hash_alg_tag = SEC_OID_SHA512; |
| 1026 break; |
| 1027 default: |
| 1028 return false; |
| 1029 } |
| 1030 |
| 1031 *signature_match = |
| 1032 SECSuccess == VFY_VerifyDataDirect(data, |
| 1033 data_size, |
| 1034 public_key->key(), |
| 1035 &signature_item, |
| 1036 SEC_OID_PKCS1_RSA_ENCRYPTION, |
| 1037 hash_alg_tag, |
| 1038 NULL, |
| 1039 NULL); |
| 1040 |
| 1041 break; |
| 1042 } |
936 default: | 1043 default: |
937 return false; | 1044 return false; |
938 } | 1045 } |
939 | 1046 |
940 return true; | 1047 return true; |
941 } | 1048 } |
942 | 1049 |
943 bool WebCryptoImpl::ImportRsaPublicKeyInternal( | 1050 bool WebCryptoImpl::ImportRsaPublicKeyInternal( |
944 const unsigned char* modulus_data, | 1051 const unsigned char* modulus_data, |
945 unsigned modulus_size, | 1052 unsigned modulus_size, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 | 1099 |
993 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), | 1100 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), |
994 blink::WebCryptoKeyTypePublic, | 1101 blink::WebCryptoKeyTypePublic, |
995 extractable, | 1102 extractable, |
996 algorithm, | 1103 algorithm, |
997 usage_mask); | 1104 usage_mask); |
998 return true; | 1105 return true; |
999 } | 1106 } |
1000 | 1107 |
1001 } // namespace content | 1108 } // namespace content |
OLD | NEW |