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 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |