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

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: minor code formatting fix Created 6 years, 11 months 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
« no previous file with comments | « no previous file | content/renderer/webcrypto/webcrypto_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 case blink::WebCryptoAlgorithmIdAesCbc: 430 case blink::WebCryptoAlgorithmIdAesCbc:
431 case blink::WebCryptoAlgorithmIdAesKw: 431 case blink::WebCryptoAlgorithmIdAesKw:
432 case blink::WebCryptoAlgorithmIdAesGcm: 432 case blink::WebCryptoAlgorithmIdAesGcm:
433 type = blink::WebCryptoKeyTypeSecret; 433 type = blink::WebCryptoKeyTypeSecret;
434 break; 434 break;
435 // TODO(bryaneyler): Support more key types. 435 // TODO(bryaneyler): Support more key types.
436 default: 436 default:
437 return false; 437 return false;
438 } 438 }
439 439
440 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
441 // Currently only supporting symmetric.
440 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; 442 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
441 // Flags are verified at the Blink layer; here the flags are set to all 443 // Flags are verified at the Blink layer; here the flags are set to all
442 // possible operations for this key type. 444 // possible operations for this key type.
443 CK_FLAGS flags = 0; 445 CK_FLAGS flags = 0;
444 446
445 switch (algorithm.id()) { 447 switch (algorithm.id()) {
446 case blink::WebCryptoAlgorithmIdHmac: { 448 case blink::WebCryptoAlgorithmIdHmac: {
447 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); 449 const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
448 if (!params) { 450 if (!params) {
449 return false; 451 return false;
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 return false; 1053 return false;
1052 } 1054 }
1053 } 1055 }
1054 1056
1055 bool WebCryptoImpl::SignInternal( 1057 bool WebCryptoImpl::SignInternal(
1056 const blink::WebCryptoAlgorithm& algorithm, 1058 const blink::WebCryptoAlgorithm& algorithm,
1057 const blink::WebCryptoKey& key, 1059 const blink::WebCryptoKey& key,
1058 const unsigned char* data, 1060 const unsigned char* data,
1059 unsigned data_size, 1061 unsigned data_size,
1060 blink::WebArrayBuffer* buffer) { 1062 blink::WebArrayBuffer* buffer) {
1063
1064 // Note: It is not an error to sign empty data.
1065
1066 DCHECK(buffer);
1067 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
1068
1061 blink::WebArrayBuffer result; 1069 blink::WebArrayBuffer result;
1062 1070
1063 switch (algorithm.id()) { 1071 switch (algorithm.id()) {
1064 case blink::WebCryptoAlgorithmIdHmac: { 1072 case blink::WebCryptoAlgorithmIdHmac: {
1065 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); 1073 const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
1066 if (!params) { 1074 if (!params) {
1067 return false; 1075 return false;
1068 } 1076 }
1069 1077
1070 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); 1078 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
1071 1079
1072 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), 1080 DCHECK_EQ(PK11_GetMechanism(sym_key->key()),
1073 WebCryptoHashToHMACMechanism(params->hash())); 1081 WebCryptoHashToHMACMechanism(params->hash()));
1074 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
1075 1082
1076 SECItem param_item = { siBuffer, NULL, 0 }; 1083 SECItem param_item = { siBuffer, NULL, 0 };
1077 SECItem data_item = { 1084 SECItem data_item = {
1078 siBuffer, 1085 siBuffer,
1079 const_cast<unsigned char*>(data), 1086 const_cast<unsigned char*>(data),
1080 data_size 1087 data_size
1081 }; 1088 };
1082 // First call is to figure out the length. 1089 // First call is to figure out the length.
1083 SECItem signature_item = { siBuffer, NULL, 0 }; 1090 SECItem signature_item = { siBuffer, NULL, 0 };
1084 1091
(...skipping 17 matching lines...) Expand all
1102 &signature_item, 1109 &signature_item,
1103 &data_item) != SECSuccess) { 1110 &data_item) != SECSuccess) {
1104 NOTREACHED(); 1111 NOTREACHED();
1105 return false; 1112 return false;
1106 } 1113 }
1107 1114
1108 DCHECK_EQ(result.byteLength(), signature_item.len); 1115 DCHECK_EQ(result.byteLength(), signature_item.len);
1109 1116
1110 break; 1117 break;
1111 } 1118 }
1119 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: {
1120 if (key.type() != blink::WebCryptoKeyTypePrivate ||
1121 webcrypto::GetInnerHashAlgorithm(algorithm).isNull())
1122 return false;
1123
1124 PrivateKeyHandle* const private_key =
1125 reinterpret_cast<PrivateKeyHandle*>(key.handle());
1126 DCHECK(private_key);
1127 DCHECK(private_key->key());
1128
1129 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the
1130 // inner hash of the input Web Crypto algorithm.
1131 SECOidTag sign_alg_tag;
1132 switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) {
1133 case blink::WebCryptoAlgorithmIdSha1:
1134 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1135 break;
1136 case blink::WebCryptoAlgorithmIdSha224:
1137 sign_alg_tag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION;
1138 break;
1139 case blink::WebCryptoAlgorithmIdSha256:
1140 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1141 break;
1142 case blink::WebCryptoAlgorithmIdSha384:
1143 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1144 break;
1145 case blink::WebCryptoAlgorithmIdSha512:
1146 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
1147 break;
1148 default:
1149 return false;
1150 }
1151
1152 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0));
1153 if (SEC_SignData(signature_item.get(),
1154 data,
1155 data_size,
1156 private_key->key(),
1157 sign_alg_tag) != SECSuccess) {
1158 return false;
1159 }
1160
1161 result = webcrypto::CreateArrayBuffer(signature_item->data,
1162 signature_item->len);
1163
1164 break;
1165 }
1112 default: 1166 default:
1113 return false; 1167 return false;
1114 } 1168 }
1115 1169
1116 *buffer = result; 1170 *buffer = result;
1117 return true; 1171 return true;
1118 } 1172 }
1119 1173
1120 bool WebCryptoImpl::VerifySignatureInternal( 1174 bool WebCryptoImpl::VerifySignatureInternal(
1121 const blink::WebCryptoAlgorithm& algorithm, 1175 const blink::WebCryptoAlgorithm& algorithm,
1122 const blink::WebCryptoKey& key, 1176 const blink::WebCryptoKey& key,
1123 const unsigned char* signature, 1177 const unsigned char* signature,
1124 unsigned signature_size, 1178 unsigned signature_size,
1125 const unsigned char* data, 1179 const unsigned char* data,
1126 unsigned data_size, 1180 unsigned data_size,
1127 bool* signature_match) { 1181 bool* signature_match) {
1182
1183 if (!signature_size)
1184 return false;
1185 DCHECK(signature);
1186
1128 switch (algorithm.id()) { 1187 switch (algorithm.id()) {
1129 case blink::WebCryptoAlgorithmIdHmac: { 1188 case blink::WebCryptoAlgorithmIdHmac: {
1130 blink::WebArrayBuffer result; 1189 blink::WebArrayBuffer result;
1131 if (!SignInternal(algorithm, key, data, data_size, &result)) { 1190 if (!SignInternal(algorithm, key, data, data_size, &result)) {
1132 return false; 1191 return false;
1133 } 1192 }
1134 1193
1135 // Handling of truncated signatures is underspecified in the WebCrypto 1194 // Handling of truncated signatures is underspecified in the WebCrypto
1136 // spec, so here we fail verification if a truncated signature is being 1195 // spec, so here we fail verification if a truncated signature is being
1137 // verified. 1196 // verified.
1138 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 1197 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097
1139 *signature_match = 1198 *signature_match =
1140 result.byteLength() == signature_size && 1199 result.byteLength() == signature_size &&
1141 crypto::SecureMemEqual(result.data(), signature, signature_size); 1200 crypto::SecureMemEqual(result.data(), signature, signature_size);
1142 1201
1143 break; 1202 break;
1144 } 1203 }
1204 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: {
1205 if (key.type() != blink::WebCryptoKeyTypePublic)
1206 return false;
1207
1208 PublicKeyHandle* const public_key =
1209 reinterpret_cast<PublicKeyHandle*>(key.handle());
1210 DCHECK(public_key);
1211 DCHECK(public_key->key());
1212
1213 const SECItem signature_item = {
1214 siBuffer,
1215 const_cast<unsigned char*>(signature),
1216 signature_size
1217 };
1218
1219 SECOidTag hash_alg_tag;
1220 switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) {
1221 case blink::WebCryptoAlgorithmIdSha1:
1222 hash_alg_tag = SEC_OID_SHA1;
1223 break;
1224 case blink::WebCryptoAlgorithmIdSha224:
1225 hash_alg_tag = SEC_OID_SHA224;
1226 break;
1227 case blink::WebCryptoAlgorithmIdSha256:
1228 hash_alg_tag = SEC_OID_SHA256;
1229 break;
1230 case blink::WebCryptoAlgorithmIdSha384:
1231 hash_alg_tag = SEC_OID_SHA384;
1232 break;
1233 case blink::WebCryptoAlgorithmIdSha512:
1234 hash_alg_tag = SEC_OID_SHA512;
1235 break;
1236 default:
1237 return false;
1238 }
1239
1240 *signature_match =
1241 SECSuccess == VFY_VerifyDataDirect(data,
1242 data_size,
1243 public_key->key(),
1244 &signature_item,
1245 SEC_OID_PKCS1_RSA_ENCRYPTION,
1246 hash_alg_tag,
1247 NULL,
1248 NULL);
1249
1250 break;
1251 }
1145 default: 1252 default:
1146 return false; 1253 return false;
1147 } 1254 }
1148 1255
1149 return true; 1256 return true;
1150 } 1257 }
1151 1258
1152 bool WebCryptoImpl::ImportRsaPublicKeyInternal( 1259 bool WebCryptoImpl::ImportRsaPublicKeyInternal(
1153 const unsigned char* modulus_data, 1260 const unsigned char* modulus_data,
1154 unsigned modulus_size, 1261 unsigned modulus_size,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1201 1308
1202 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), 1309 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()),
1203 blink::WebCryptoKeyTypePublic, 1310 blink::WebCryptoKeyTypePublic,
1204 extractable, 1311 extractable,
1205 algorithm, 1312 algorithm,
1206 usage_mask); 1313 usage_mask);
1207 return true; 1314 return true;
1208 } 1315 }
1209 1316
1210 } // namespace content 1317 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/renderer/webcrypto/webcrypto_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698