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

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 MAYBE'ed new tests (missed in last 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 DCHECK(!algorithm.isNull());
86 switch (algorithm.id()) {
87 case blink::WebCryptoAlgorithmIdSha1:
88 return SEC_OID_SHA1;
89 case blink::WebCryptoAlgorithmIdSha224:
90 return SEC_OID_SHA224;
91 case blink::WebCryptoAlgorithmIdSha256:
92 return SEC_OID_SHA256;
93 case blink::WebCryptoAlgorithmIdSha384:
94 return SEC_OID_SHA384;
95 case blink::WebCryptoAlgorithmIdSha512:
96 return SEC_OID_SHA512;
97 default:
98 return SEC_OID_UNKNOWN;
99 }
100 }
101
83 CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism( 102 CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism(
84 const blink::WebCryptoAlgorithm& algorithm) { 103 const blink::WebCryptoAlgorithm& algorithm) {
85 switch (algorithm.id()) { 104 switch (algorithm.id()) {
86 case blink::WebCryptoAlgorithmIdSha1: 105 case blink::WebCryptoAlgorithmIdSha1:
87 return CKM_SHA_1_HMAC; 106 return CKM_SHA_1_HMAC;
88 case blink::WebCryptoAlgorithmIdSha256: 107 case blink::WebCryptoAlgorithmIdSha256:
89 return CKM_SHA256_HMAC; 108 return CKM_SHA256_HMAC;
90 default: 109 default:
91 // Not a supported algorithm. 110 // Not a supported algorithm.
92 return CKM_INVALID_MECHANISM; 111 return CKM_INVALID_MECHANISM;
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 case blink::WebCryptoAlgorithmIdHmac: 280 case blink::WebCryptoAlgorithmIdHmac:
262 case blink::WebCryptoAlgorithmIdAesCbc: 281 case blink::WebCryptoAlgorithmIdAesCbc:
263 case blink::WebCryptoAlgorithmIdAesKw: 282 case blink::WebCryptoAlgorithmIdAesKw:
264 type = blink::WebCryptoKeyTypeSecret; 283 type = blink::WebCryptoKeyTypeSecret;
265 break; 284 break;
266 // TODO(bryaneyler): Support more key types. 285 // TODO(bryaneyler): Support more key types.
267 default: 286 default:
268 return false; 287 return false;
269 } 288 }
270 289
290 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
291 // Currently only supporting symmetric.
271 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; 292 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
272 // Flags are verified at the Blink layer; here the flags are set to all 293 // Flags are verified at the Blink layer; here the flags are set to all
273 // possible operations for this key type. 294 // possible operations for this key type.
274 CK_FLAGS flags = 0; 295 CK_FLAGS flags = 0;
275 296
276 switch (algorithm.id()) { 297 switch (algorithm.id()) {
277 case blink::WebCryptoAlgorithmIdHmac: { 298 case blink::WebCryptoAlgorithmIdHmac: {
278 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); 299 const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
279 if (!params) { 300 if (!params) {
280 return false; 301 return false;
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 return false; 882 return false;
862 } 883 }
863 } 884 }
864 885
865 bool WebCryptoImpl::SignInternal( 886 bool WebCryptoImpl::SignInternal(
866 const blink::WebCryptoAlgorithm& algorithm, 887 const blink::WebCryptoAlgorithm& algorithm,
867 const blink::WebCryptoKey& key, 888 const blink::WebCryptoKey& key,
868 const unsigned char* data, 889 const unsigned char* data,
869 unsigned data_size, 890 unsigned data_size,
870 blink::WebArrayBuffer* buffer) { 891 blink::WebArrayBuffer* buffer) {
892
893 // Note: It is not an error to sign empty data.
894
895 DCHECK(buffer);
896 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
897
871 blink::WebArrayBuffer result; 898 blink::WebArrayBuffer result;
872 899
873 switch (algorithm.id()) { 900 switch (algorithm.id()) {
874 case blink::WebCryptoAlgorithmIdHmac: { 901 case blink::WebCryptoAlgorithmIdHmac: {
875 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); 902 const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
876 if (!params) { 903 if (!params) {
877 return false; 904 return false;
878 } 905 }
879 906
880 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); 907 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
881 908
882 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), 909 DCHECK_EQ(PK11_GetMechanism(sym_key->key()),
883 WebCryptoAlgorithmToHMACMechanism(params->hash())); 910 WebCryptoAlgorithmToHMACMechanism(params->hash()));
884 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
885 911
886 SECItem param_item = { siBuffer, NULL, 0 }; 912 SECItem param_item = { siBuffer, NULL, 0 };
887 SECItem data_item = { 913 SECItem data_item = {
888 siBuffer, 914 siBuffer,
889 const_cast<unsigned char*>(data), 915 const_cast<unsigned char*>(data),
890 data_size 916 data_size
891 }; 917 };
892 // First call is to figure out the length. 918 // First call is to figure out the length.
893 SECItem signature_item = { siBuffer, NULL, 0 }; 919 SECItem signature_item = { siBuffer, NULL, 0 };
894 920
(...skipping 17 matching lines...) Expand all
912 &signature_item, 938 &signature_item,
913 &data_item) != SECSuccess) { 939 &data_item) != SECSuccess) {
914 NOTREACHED(); 940 NOTREACHED();
915 return false; 941 return false;
916 } 942 }
917 943
918 DCHECK_EQ(result.byteLength(), signature_item.len); 944 DCHECK_EQ(result.byteLength(), signature_item.len);
919 945
920 break; 946 break;
921 } 947 }
948 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: {
949 // Only private key signing is supported.
950 if (key.type() != blink::WebCryptoKeyTypePrivate)
951 return false;
952
953 PrivateKeyHandle* const private_key =
954 reinterpret_cast<PrivateKeyHandle*>(key.handle());
955 DCHECK(private_key);
956 DCHECK(private_key->key());
957
958 // Get the inner hash algorithm and convert to an NSS SECOidTag
959 const blink::WebCryptoAlgorithm hash_algorithm =
960 webcrypto::GetInnerHashAlgorithm(algorithm);
961 if (hash_algorithm.isNull()) // TODO(padolph): DCHECK instead?
962 return false;
963 const SECOidTag hash_alg_tag =
964 WebCryptoAlgorithmToNssSecOidShaTag(hash_algorithm);
965 if (hash_alg_tag == SEC_OID_UNKNOWN)
966 return false;
967
968 // Get the NSS signature algorithm SECOidTag corresponding to the key type
969 // and inner hash algorithm SECOidTag.
970 const SECOidTag sign_alg_tag = SEC_GetSignatureAlgorithmOidTag(
971 private_key->key()->keyType,
972 hash_alg_tag);
Ryan Sleevi 2013/12/20 02:08:50 This is unnecessary. The design of this API was me
padolph 2013/12/21 02:44:17 Done.
973 if (sign_alg_tag == SEC_OID_UNKNOWN)
974 return false;
975
976 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0));
977 if (SEC_SignData(signature_item.get(),
978 data,
979 data_size,
980 private_key->key(),
981 sign_alg_tag) != SECSuccess) {
982 return false;
983 }
984
985 result = webcrypto::CreateArrayBuffer(signature_item->data,
986 signature_item->len);
987
988 break;
989 }
922 default: 990 default:
923 return false; 991 return false;
924 } 992 }
925 993
926 *buffer = result; 994 *buffer = result;
927 return true; 995 return true;
928 } 996 }
929 997
930 bool WebCryptoImpl::VerifySignatureInternal( 998 bool WebCryptoImpl::VerifySignatureInternal(
931 const blink::WebCryptoAlgorithm& algorithm, 999 const blink::WebCryptoAlgorithm& algorithm,
932 const blink::WebCryptoKey& key, 1000 const blink::WebCryptoKey& key,
933 const unsigned char* signature, 1001 const unsigned char* signature,
934 unsigned signature_size, 1002 unsigned signature_size,
935 const unsigned char* data, 1003 const unsigned char* data,
936 unsigned data_size, 1004 unsigned data_size,
937 bool* signature_match) { 1005 bool* signature_match) {
1006
1007 if (!signature_size)
1008 return false;
1009 DCHECK(signature);
1010
938 switch (algorithm.id()) { 1011 switch (algorithm.id()) {
939 case blink::WebCryptoAlgorithmIdHmac: { 1012 case blink::WebCryptoAlgorithmIdHmac: {
940 blink::WebArrayBuffer result; 1013 blink::WebArrayBuffer result;
941 if (!SignInternal(algorithm, key, data, data_size, &result)) { 1014 if (!SignInternal(algorithm, key, data, data_size, &result)) {
942 return false; 1015 return false;
943 } 1016 }
944 1017
945 // Handling of truncated signatures is underspecified in the WebCrypto 1018 // Handling of truncated signatures is underspecified in the WebCrypto
946 // spec, so here we fail verification if a truncated signature is being 1019 // spec, so here we fail verification if a truncated signature is being
947 // verified. 1020 // verified.
948 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 1021 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097
949 *signature_match = 1022 *signature_match =
950 result.byteLength() == signature_size && 1023 result.byteLength() == signature_size &&
951 crypto::SecureMemEqual(result.data(), signature, signature_size); 1024 crypto::SecureMemEqual(result.data(), signature, signature_size);
952 1025
953 break; 1026 break;
954 } 1027 }
1028 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: {
1029
Ryan Sleevi 2013/12/20 02:08:50 unnecessary newline
padolph 2013/12/21 02:44:17 Done.
1030 // Only public key signature verification is supported.
Ryan Sleevi 2013/12/20 02:08:50 This comment makes no sense, given the algorithm b
padolph 2013/12/21 02:44:17 Done.
1031 if (key.type() != blink::WebCryptoKeyTypePublic)
1032 return false;
1033
1034 PublicKeyHandle* const public_key =
1035 reinterpret_cast<PublicKeyHandle*>(key.handle());
1036 DCHECK(public_key);
1037 DCHECK(public_key->key());
1038
1039 const SECItem signature_item = {
1040 siBuffer,
1041 const_cast<unsigned char*>(signature),
1042 signature_size
1043 };
1044
1045 const SECOidTag hash_alg_tag = WebCryptoAlgorithmToNssSecOidShaTag(
1046 webcrypto::GetInnerHashAlgorithm(algorithm));
1047 if (hash_alg_tag == SEC_OID_UNKNOWN)
1048 return false;
1049
1050 *signature_match =
1051 VFY_VerifyDataDirect(
1052 data,
1053 data_size,
1054 public_key->key(),
1055 &signature_item,
1056 SEC_OID_PKCS1_RSA_ENCRYPTION,
1057 hash_alg_tag,
1058 NULL,
1059 NULL) == SECSuccess;
Ryan Sleevi 2013/12/20 02:08:50 Was this run through git cl format? The formatting
padolph 2013/12/21 02:44:17 Rewrote yoda style and reformatted, and ran throug
1060
1061 break;
1062 }
955 default: 1063 default:
956 return false; 1064 return false;
957 } 1065 }
958 1066
959 return true; 1067 return true;
960 } 1068 }
961 1069
962 bool WebCryptoImpl::ImportRsaPublicKeyInternal( 1070 bool WebCryptoImpl::ImportRsaPublicKeyInternal(
963 const unsigned char* modulus_data, 1071 const unsigned char* modulus_data,
964 unsigned modulus_size, 1072 unsigned modulus_size,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 1119
1012 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), 1120 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()),
1013 blink::WebCryptoKeyTypePublic, 1121 blink::WebCryptoKeyTypePublic,
1014 extractable, 1122 extractable,
1015 algorithm, 1123 algorithm,
1016 usage_mask); 1124 usage_mask);
1017 return true; 1125 return true;
1018 } 1126 }
1019 1127
1020 } // namespace content 1128 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698