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 3 // found in the LICENSE file. 4 5 #include "content/renderer/webcrypto/webcrypto_util.h" 6 7 #include "base/base64.h" 8 #include "base/logging.h" 9 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 10 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 11 12 namespace content { 13 14 namespace webcrypto { 15 16 namespace { 17 18 blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm( 19 blink::WebCryptoAlgorithmId aes_alg_id, 20 unsigned short length) { 21 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 22 aes_alg_id, new blink::WebCryptoAesKeyGenParams(length)); 23 } 24 25 bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) { 26 return alg_id == blink::WebCryptoAlgorithmIdSha1 || 27 alg_id == blink::WebCryptoAlgorithmIdSha224 || 28 alg_id == blink::WebCryptoAlgorithmIdSha256 || 29 alg_id == blink::WebCryptoAlgorithmIdSha384 || 30 alg_id == blink::WebCryptoAlgorithmIdSha512; 31 } 32 33 } // namespace 34 35 const uint8* Uint8VectorStart(const std::vector<uint8>& data) { 36 if (data.empty()) 37 return NULL; 38 return &data[0]; 39 } 40 41 void ShrinkBuffer(blink::WebArrayBuffer* buffer, unsigned new_size) { 42 DCHECK_LE(new_size, buffer->byteLength()); 43 44 if (new_size == buffer->byteLength()) 45 return; 46 47 blink::WebArrayBuffer new_buffer = blink::WebArrayBuffer::create(new_size, 1); 48 DCHECK(!new_buffer.isNull()); 49 memcpy(new_buffer.data(), buffer->data(), new_size); 50 *buffer = new_buffer; 51 } 52 53 blink::WebArrayBuffer CreateArrayBuffer(const uint8* data, unsigned data_size) { 54 blink::WebArrayBuffer buffer = blink::WebArrayBuffer::create(data_size, 1); 55 DCHECK(!buffer.isNull()); 56 if (data_size) // data_size == 0 might mean the data pointer is invalid 57 memcpy(buffer.data(), data, data_size); 58 return buffer; 59 } 60 61 // This function decodes unpadded 'base64url' encoded data, as described in 62 // RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5. To do this, first 63 // change the incoming data to 'base64' encoding by applying the appropriate 64 // transformation including adding padding if required, and then call a base64 65 // decoder. 66 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { 67 std::string base64EncodedText(input); 68 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); 69 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); 70 base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); 71 return base::Base64Decode(base64EncodedText, output); 72 } 73 74 blink::WebCryptoAlgorithm GetInnerHashAlgorithm( 75 const blink::WebCryptoAlgorithm& algorithm) { 76 if (algorithm.hmacParams()) 77 return algorithm.hmacParams()->hash(); 78 if (algorithm.hmacKeyParams()) 79 return algorithm.hmacKeyParams()->hash(); 80 if (algorithm.rsaSsaParams()) 81 return algorithm.rsaSsaParams()->hash(); 82 if (algorithm.rsaOaepParams()) 83 return algorithm.rsaOaepParams()->hash(); 84 return blink::WebCryptoAlgorithm::createNull(); 85 } 86 87 blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) { 88 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); 89 } 90 91 blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashOutputLen( 92 unsigned short hash_output_length_bits) { 93 blink::WebCryptoAlgorithmId hash_id; 94 switch (hash_output_length_bits) { 95 case 160: 96 hash_id = blink::WebCryptoAlgorithmIdSha1; 97 break; 98 case 224: 99 hash_id = blink::WebCryptoAlgorithmIdSha224; 100 break; 101 case 256: 102 hash_id = blink::WebCryptoAlgorithmIdSha256; 103 break; 104 case 384: 105 hash_id = blink::WebCryptoAlgorithmIdSha384; 106 break; 107 case 512: 108 hash_id = blink::WebCryptoAlgorithmIdSha512; 109 break; 110 default: 111 NOTREACHED(); 112 return blink::WebCryptoAlgorithm::createNull(); 113 } 114 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 115 blink::WebCryptoAlgorithmIdHmac, 116 new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id))); 117 } 118 119 blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashId( 120 blink::WebCryptoAlgorithmId hash_id) { 121 DCHECK(IsHashAlgorithm(hash_id)); 122 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 123 blink::WebCryptoAlgorithmIdHmac, 124 new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id))); 125 } 126 127 blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm( 128 blink::WebCryptoAlgorithmId hash_id, 129 unsigned key_length_bytes) { 130 DCHECK(IsHashAlgorithm(hash_id)); 131 // key_length_bytes == 0 means unspecified 132 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 133 blink::WebCryptoAlgorithmIdHmac, 134 new blink::WebCryptoHmacKeyParams( 135 CreateAlgorithm(hash_id), (key_length_bytes != 0), key_length_bytes)); 136 } 137 138 blink::WebCryptoAlgorithm CreateRsaSsaAlgorithm( 139 blink::WebCryptoAlgorithmId hash_id) { 140 DCHECK(IsHashAlgorithm(hash_id)); 141 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 142 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 143 new blink::WebCryptoRsaSsaParams(CreateAlgorithm(hash_id))); 144 } 145 146 blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm( 147 blink::WebCryptoAlgorithmId hash_id) { 148 DCHECK(IsHashAlgorithm(hash_id)); 149 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 150 blink::WebCryptoAlgorithmIdRsaOaep, 151 new blink::WebCryptoRsaOaepParams( 152 CreateAlgorithm(hash_id), false, NULL, 0)); 153 } 154 155 blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm( 156 blink::WebCryptoAlgorithmId algorithm_id, 157 unsigned modulus_length, 158 const std::vector<uint8>& public_exponent) { 159 DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || 160 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || 161 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep); 162 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 163 algorithm_id, 164 new blink::WebCryptoRsaKeyGenParams( 165 modulus_length, 166 webcrypto::Uint8VectorStart(public_exponent), 167 public_exponent.size())); 168 } 169 170 blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(const std::vector<uint8>& iv) { 171 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 172 blink::WebCryptoAlgorithmIdAesCbc, 173 new blink::WebCryptoAesCbcParams(Uint8VectorStart(iv), iv.size())); 174 } 175 176 blink::WebCryptoAlgorithm CreateAesGcmAlgorithm( 177 const std::vector<uint8>& iv, 178 const std::vector<uint8>& additional_data, 179 uint8 tag_length_bytes) { 180 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 181 blink::WebCryptoAlgorithmIdAesCbc, 182 new blink::WebCryptoAesGcmParams(Uint8VectorStart(iv), 183 iv.size(), 184 additional_data.size() != 0, 185 Uint8VectorStart(additional_data), 186 additional_data.size(), 187 tag_length_bytes != 0, 188 tag_length_bytes)); 189 } 190 191 blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm( 192 unsigned short key_length_bits) { 193 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc, 194 key_length_bits); 195 } 196 197 blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm( 198 unsigned short key_length_bits) { 199 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm, 200 key_length_bits); 201 } 202 203 } // namespace webcrypto 204 205 } // namespace content 206