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

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 and rebase 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 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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698