OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/platform_crypto.h" | 5 #include "content/renderer/webcrypto/platform_crypto.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 1108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1119 // max limit is whatever will fit into an unsigned. For the max size test, | 1119 // max limit is whatever will fit into an unsigned. For the max size test, |
1120 // note that AES Key Wrap always adds 8 bytes to the input data size. | 1120 // note that AES Key Wrap always adds 8 bytes to the input data size. |
1121 const unsigned int input_length = PK11_GetKeyLength(key->key()); | 1121 const unsigned int input_length = PK11_GetKeyLength(key->key()); |
1122 if (input_length < 16) | 1122 if (input_length < 16) |
1123 return Status::ErrorDataTooSmall(); | 1123 return Status::ErrorDataTooSmall(); |
1124 if (input_length > UINT_MAX - 8) | 1124 if (input_length > UINT_MAX - 8) |
1125 return Status::ErrorDataTooLarge(); | 1125 return Status::ErrorDataTooLarge(); |
1126 if (input_length % 8) | 1126 if (input_length % 8) |
1127 return Status::ErrorInvalidAesKwDataLength(); | 1127 return Status::ErrorInvalidAesKwDataLength(); |
1128 | 1128 |
1129 SECItem iv_item = | 1129 SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv))); |
1130 MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv))); | |
1131 crypto::ScopedSECItem param_item( | 1130 crypto::ScopedSECItem param_item( |
1132 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); | 1131 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); |
1133 if (!param_item) | 1132 if (!param_item) |
1134 return Status::ErrorUnexpected(); | 1133 return Status::ErrorUnexpected(); |
1135 | 1134 |
1136 const unsigned int output_length = input_length + 8; | 1135 const unsigned int output_length = input_length + 8; |
1137 *buffer = blink::WebArrayBuffer::create(output_length, 1); | 1136 *buffer = blink::WebArrayBuffer::create(output_length, 1); |
1138 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); | 1137 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); |
1139 SECItem wrapped_key_item = {siBuffer, buffer_data, output_length}; | |
1140 | 1138 |
1141 if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP, | 1139 if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP, |
1142 param_item.get(), | 1140 param_item.get(), |
1143 wrapping_key->key(), | 1141 wrapping_key->key(), |
1144 key->key(), | 1142 key->key(), |
1145 &wrapped_key_item)) { | 1143 &wrapped_key_item)) { |
1146 return Status::Error(); | 1144 return Status::Error(); |
1147 } | 1145 } |
1148 if (output_length != wrapped_key_item.len) | 1146 if (output_length != wrapped_key_item.len) |
1149 return Status::ErrorUnexpected(); | 1147 return Status::ErrorUnexpected(); |
1150 | 1148 |
1151 return Status::Success(); | 1149 return Status::Success(); |
1152 } | 1150 } |
1153 | 1151 |
1154 Status UnwrapSymKeyAesKw(const CryptoData& wrapped_key_data, | 1152 Status UnwrapSymKeyAesKw(const CryptoData& wrapped_key_data, |
1155 SymKey* wrapping_key, | 1153 SymKey* wrapping_key, |
1156 const blink::WebCryptoAlgorithm& algorithm, | 1154 const blink::WebCryptoAlgorithm& algorithm, |
1157 bool extractable, | 1155 bool extractable, |
1158 blink::WebCryptoKeyUsageMask usage_mask, | 1156 blink::WebCryptoKeyUsageMask usage_mask, |
1159 blink::WebCryptoKey* key) { | 1157 blink::WebCryptoKey* key) { |
1160 DCHECK_GE(wrapped_key_data.byte_length(), 24u); | 1158 DCHECK_GE(wrapped_key_data.byte_length(), 24u); |
1161 DCHECK_EQ(wrapped_key_data.byte_length() % 8, 0u); | 1159 DCHECK_EQ(wrapped_key_data.byte_length() % 8, 0u); |
1162 | 1160 |
1163 SECItem iv_item = | 1161 SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv))); |
1164 MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv))); | |
1165 crypto::ScopedSECItem param_item( | 1162 crypto::ScopedSECItem param_item( |
1166 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); | 1163 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); |
1167 if (!param_item) | 1164 if (!param_item) |
1168 return Status::ErrorUnexpected(); | 1165 return Status::ErrorUnexpected(); |
1169 | 1166 |
1170 SECItem cipher_text = MakeSECItemForBuffer(wrapped_key_data); | 1167 SECItem cipher_text = MakeSECItemForBuffer(wrapped_key_data); |
1171 | 1168 |
1172 // The plaintext length is always 64 bits less than the data size. | 1169 // The plaintext length is always 64 bits less than the data size. |
1173 const unsigned int plaintext_length = wrapped_key_data.byte_length() - 8; | 1170 const unsigned int plaintext_length = wrapped_key_data.byte_length() - 8; |
1174 | 1171 |
(...skipping 22 matching lines...) Expand all Loading... | |
1197 return Status::ErrorUnexpected(); | 1194 return Status::ErrorUnexpected(); |
1198 | 1195 |
1199 *key = blink::WebCryptoKey::create(new SymKey(unwrapped_key.Pass()), | 1196 *key = blink::WebCryptoKey::create(new SymKey(unwrapped_key.Pass()), |
1200 blink::WebCryptoKeyTypeSecret, | 1197 blink::WebCryptoKeyTypeSecret, |
1201 extractable, | 1198 extractable, |
1202 key_algorithm, | 1199 key_algorithm, |
1203 usage_mask); | 1200 usage_mask); |
1204 return Status::Success(); | 1201 return Status::Success(); |
1205 } | 1202 } |
1206 | 1203 |
1204 Status WrapSymKeyRsaEs(PublicKey* wrapping_key, | |
1205 SymKey* key, | |
1206 blink::WebArrayBuffer* buffer) { | |
1207 // Check the raw length of the key to be wrapped against the max size allowed | |
1208 // by the RSA wrapping key. With PKCS#1 v1.5 padding used in this function, | |
1209 // the maximum data length that can be encrypted is the wrapping_key's modulus | |
1210 // byte length minus eleven bytes. | |
1211 const unsigned int input_length_bytes = PK11_GetKeyLength(key->key()); | |
1212 const unsigned int modulus_length_bytes = | |
1213 SECKEY_PublicKeyStrength(wrapping_key->key()); | |
1214 if (input_length_bytes > modulus_length_bytes - 11) | |
eroman
2014/03/06 04:31:16
Is it possible for modulus_length_bytes to be < 11
padolph
2014/03/10 19:02:54
Extremely unlikely as it would be very bad securit
| |
1215 return Status::ErrorDataTooLarge(); | |
1216 | |
1217 *buffer = blink::WebArrayBuffer::create(modulus_length_bytes, 1); | |
1218 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); | |
1219 | |
1220 if (SECSuccess != | |
1221 PK11_PubWrapSymKey( | |
eroman
2014/03/06 04:31:16
is this the automated formatting? I think it needs
padolph
2014/03/10 19:02:54
Yes. I run 'git cl format' before upload now. Will
| |
1222 CKM_RSA_PKCS, wrapping_key->key(), key->key(), &wrapped_key_item)) { | |
1223 return Status::Error(); | |
1224 } | |
1225 if (wrapped_key_item.len != modulus_length_bytes) | |
1226 return Status::ErrorUnexpected(); | |
1227 | |
1228 return Status::Success(); | |
1229 } | |
1230 | |
1231 Status UnwrapSymKeyRsaEs(const CryptoData& wrapped_key_data, | |
1232 PrivateKey* wrapping_key, | |
1233 const blink::WebCryptoAlgorithm& algorithm, | |
1234 bool extractable, | |
1235 blink::WebCryptoKeyUsageMask usage_mask, | |
1236 blink::WebCryptoKey* key) { | |
1237 | |
1238 // Verify wrapped_key_data size does not exceed the modulus of the RSA key. | |
1239 const int modulus_length_bytes = | |
1240 PK11_GetPrivateModulusLen(wrapping_key->key()); | |
1241 if (modulus_length_bytes <= 0) | |
1242 return Status::ErrorUnexpected(); | |
1243 if (wrapped_key_data.byte_length() > | |
1244 static_cast<unsigned int>(modulus_length_bytes)) | |
1245 return Status::ErrorDataTooLarge(); | |
1246 | |
1247 // Determine the proper NSS key properties from the input algorithm. | |
1248 CK_MECHANISM_TYPE mechanism; | |
1249 CK_FLAGS flags; | |
1250 Status status = | |
1251 WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags); | |
1252 if (status.IsError()) | |
1253 return status; | |
1254 | |
1255 SECItem wrapped_key_item = MakeSECItemForBuffer(wrapped_key_data); | |
1256 | |
1257 crypto::ScopedPK11SymKey unwrapped_key( | |
1258 PK11_PubUnwrapSymKeyWithFlagsPerm(wrapping_key->key(), | |
1259 &wrapped_key_item, | |
1260 mechanism, | |
1261 CKA_DECRYPT, | |
1262 0, | |
1263 flags, | |
1264 false)); | |
1265 if (!unwrapped_key) | |
1266 return Status::Error(); | |
1267 | |
1268 const unsigned int key_length = PK11_GetKeyLength(unwrapped_key.get()); | |
1269 | |
1270 blink::WebCryptoKeyAlgorithm key_algorithm; | |
1271 if (!CreateSecretKeyAlgorithm(algorithm, key_length, &key_algorithm)) | |
1272 return Status::ErrorUnexpected(); | |
1273 | |
1274 *key = blink::WebCryptoKey::create(new SymKey(unwrapped_key.Pass()), | |
1275 blink::WebCryptoKeyTypeSecret, | |
1276 extractable, | |
1277 key_algorithm, | |
1278 usage_mask); | |
1279 return Status::Success(); | |
1280 } | |
1281 | |
1207 } // namespace platform | 1282 } // namespace platform |
1208 | 1283 |
1209 } // namespace webcrypto | 1284 } // namespace webcrypto |
1210 | 1285 |
1211 } // namespace content | 1286 } // namespace content |
OLD | NEW |