Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1407)

Side by Side Diff: content/renderer/webcrypto/webcrypto_impl_nss.cc

Issue 68303009: [webcrypto] Add RSASSA-PKCS1-v1_5 sign and verify for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixes for eroman Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698