| 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 |