// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/renderer/webcrypto/webcrypto_util.h" #include "base/base64.h" #include "base/logging.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" namespace content { namespace webcrypto { namespace { blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm( blink::WebCryptoAlgorithmId aes_alg_id, unsigned short length) { return blink::WebCryptoAlgorithm::adoptParamsAndCreate( aes_alg_id, new blink::WebCryptoAesKeyGenParams(length)); } bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) { return alg_id == blink::WebCryptoAlgorithmIdSha1 || alg_id == blink::WebCryptoAlgorithmIdSha224 || alg_id == blink::WebCryptoAlgorithmIdSha256 || alg_id == blink::WebCryptoAlgorithmIdSha384 || alg_id == blink::WebCryptoAlgorithmIdSha512; } } // namespace const uint8* Uint8VectorStart(const std::vector<uint8>& data) { if (data.empty()) return NULL; return &data[0]; } void ShrinkBuffer(blink::WebArrayBuffer* buffer, unsigned new_size) { DCHECK_LE(new_size, buffer->byteLength()); if (new_size == buffer->byteLength()) return; blink::WebArrayBuffer new_buffer = blink::WebArrayBuffer::create(new_size, 1); DCHECK(!new_buffer.isNull()); memcpy(new_buffer.data(), buffer->data(), new_size); *buffer = new_buffer; } blink::WebArrayBuffer CreateArrayBuffer(const uint8* data, unsigned data_size) { blink::WebArrayBuffer buffer = blink::WebArrayBuffer::create(data_size, 1); DCHECK(!buffer.isNull()); if (data_size) // data_size == 0 might mean the data pointer is invalid memcpy(buffer.data(), data, data_size); return buffer; } // This function decodes unpadded 'base64url' encoded data, as described in // RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5. To do this, first // change the incoming data to 'base64' encoding by applying the appropriate // transformation including adding padding if required, and then call a base64 // decoder. bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { std::string base64EncodedText(input); std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); return base::Base64Decode(base64EncodedText, output); } blink::WebCryptoAlgorithm GetInnerHashAlgorithm( const blink::WebCryptoAlgorithm& algorithm) { if (algorithm.hmacParams()) return algorithm.hmacParams()->hash(); if (algorithm.hmacKeyParams()) return algorithm.hmacKeyParams()->hash(); if (algorithm.rsaSsaParams()) return algorithm.rsaSsaParams()->hash(); if (algorithm.rsaOaepParams()) return algorithm.rsaOaepParams()->hash(); return blink::WebCryptoAlgorithm::createNull(); } blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) { return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); } blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashOutputLen( unsigned short hash_output_length_bits) { blink::WebCryptoAlgorithmId hash_id; switch (hash_output_length_bits) { case 160: hash_id = blink::WebCryptoAlgorithmIdSha1; break; case 224: hash_id = blink::WebCryptoAlgorithmIdSha224; break; case 256: hash_id = blink::WebCryptoAlgorithmIdSha256; break; case 384: hash_id = blink::WebCryptoAlgorithmIdSha384; break; case 512: hash_id = blink::WebCryptoAlgorithmIdSha512; break; default: NOTREACHED(); return blink::WebCryptoAlgorithm::createNull(); } return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdHmac, new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id))); } blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashId( blink::WebCryptoAlgorithmId hash_id) { DCHECK(IsHashAlgorithm(hash_id)); return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdHmac, new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id))); } blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm( blink::WebCryptoAlgorithmId hash_id, unsigned key_length_bytes) { DCHECK(IsHashAlgorithm(hash_id)); // key_length_bytes == 0 means unspecified return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdHmac, new blink::WebCryptoHmacKeyParams( CreateAlgorithm(hash_id), (key_length_bytes != 0), key_length_bytes)); } blink::WebCryptoAlgorithm CreateRsaSsaAlgorithm( blink::WebCryptoAlgorithmId hash_id) { DCHECK(IsHashAlgorithm(hash_id)); return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, new blink::WebCryptoRsaSsaParams(CreateAlgorithm(hash_id))); } blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm( blink::WebCryptoAlgorithmId hash_id) { DCHECK(IsHashAlgorithm(hash_id)); return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdRsaOaep, new blink::WebCryptoRsaOaepParams( CreateAlgorithm(hash_id), false, NULL, 0)); } blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm( blink::WebCryptoAlgorithmId algorithm_id, unsigned modulus_length, const std::vector<uint8>& public_exponent) { DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep); return blink::WebCryptoAlgorithm::adoptParamsAndCreate( algorithm_id, new blink::WebCryptoRsaKeyGenParams( modulus_length, webcrypto::Uint8VectorStart(public_exponent), public_exponent.size())); } blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(const std::vector<uint8>& iv) { return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdAesCbc, new blink::WebCryptoAesCbcParams(Uint8VectorStart(iv), iv.size())); } blink::WebCryptoAlgorithm CreateAesGcmAlgorithm( const std::vector<uint8>& iv, const std::vector<uint8>& additional_data, uint8 tag_length_bytes) { return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdAesCbc, new blink::WebCryptoAesGcmParams(Uint8VectorStart(iv), iv.size(), additional_data.size() != 0, Uint8VectorStart(additional_data), additional_data.size(), tag_length_bytes != 0, tag_length_bytes)); } blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm( unsigned short key_length_bits) { return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc, key_length_bits); } blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm( unsigned short key_length_bits) { return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm, key_length_bits); } } // namespace webcrypto } // namespace content