|
10 | 10 | #include "v8.h" |
11 | 11 |
|
12 | 12 | #include <openssl/evp.h> |
| 13 | +#ifdef OPENSSL_IS_BORINGSSL |
| 14 | +#include <openssl/aead.h> |
| 15 | +#endif |
13 | 16 |
|
14 | 17 | namespace node { |
15 | 18 |
|
@@ -110,10 +113,15 @@ Maybe<void> ChaCha20Poly1305CipherTraits::AdditionalConfig( |
110 | 113 | params->mode = mode; |
111 | 114 | params->cipher = ncrypto::Cipher::CHACHA20_POLY1305; |
112 | 115 |
|
| 116 | +#ifndef OPENSSL_IS_BORINGSSL |
| 117 | + // On BoringSSL, ChaCha20-Poly1305 is not exposed via the EVP_CIPHER registry |
| 118 | + // so FromNid() returns a null Cipher. We use EVP_AEAD directly in DoCipher |
| 119 | + // instead. |
113 | 120 | if (!params->cipher) { |
114 | 121 | THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env); |
115 | 122 | return Nothing<void>(); |
116 | 123 | } |
| 124 | +#endif |
117 | 125 |
|
118 | 126 | // IV parameter (required) |
119 | 127 | if (!ValidateIV(env, mode, args[offset], params)) { |
@@ -144,6 +152,75 @@ WebCryptoCipherStatus ChaCha20Poly1305CipherTraits::DoCipher( |
144 | 152 | return WebCryptoCipherStatus::INVALID_KEY_TYPE; |
145 | 153 | } |
146 | 154 |
|
| 155 | +#ifdef OPENSSL_IS_BORINGSSL |
| 156 | + // BoringSSL does not expose ChaCha20-Poly1305 via the EVP_CIPHER registry; |
| 157 | + // it is only available through the EVP_AEAD API. Matches Chromium's |
| 158 | + // WebCrypto ChaCha20-Poly1305 implementation. |
| 159 | + const auto key_bytes = |
| 160 | + reinterpret_cast<const unsigned char*>(key_data.GetSymmetricKey()); |
| 161 | + const auto ad_bytes = params.additional_data.data<unsigned char>(); |
| 162 | + const auto ad_len = params.additional_data.size(); |
| 163 | + const auto iv_bytes = params.iv.data<unsigned char>(); |
| 164 | + const auto iv_len = params.iv.size(); |
| 165 | + |
| 166 | + bssl::ScopedEVP_AEAD_CTX ctx; |
| 167 | + if (!EVP_AEAD_CTX_init(ctx.get(), |
| 168 | + EVP_aead_chacha20_poly1305(), |
| 169 | + key_bytes, |
| 170 | + key_data.GetSymmetricKeySize(), |
| 171 | + kChaCha20Poly1305TagSize, |
| 172 | + nullptr)) { |
| 173 | + return WebCryptoCipherStatus::FAILED; |
| 174 | + } |
| 175 | + |
| 176 | + if (cipher_mode == kWebCryptoCipherEncrypt) { |
| 177 | + size_t out_len = 0; |
| 178 | + const size_t max_out_len = in.size() + kChaCha20Poly1305TagSize; |
| 179 | + auto buf = DataPointer::Alloc(max_out_len); |
| 180 | + if (!EVP_AEAD_CTX_seal(ctx.get(), |
| 181 | + static_cast<unsigned char*>(buf.get()), |
| 182 | + &out_len, |
| 183 | + max_out_len, |
| 184 | + iv_bytes, |
| 185 | + iv_len, |
| 186 | + in.data<unsigned char>(), |
| 187 | + in.size(), |
| 188 | + ad_bytes, |
| 189 | + ad_len)) { |
| 190 | + return WebCryptoCipherStatus::FAILED; |
| 191 | + } |
| 192 | + buf = buf.resize(out_len); |
| 193 | + *out = ByteSource::Allocated(buf.release()); |
| 194 | + return WebCryptoCipherStatus::OK; |
| 195 | + } |
| 196 | + |
| 197 | + // Decrypt |
| 198 | + if (in.size() < kChaCha20Poly1305TagSize) { |
| 199 | + return WebCryptoCipherStatus::FAILED; |
| 200 | + } |
| 201 | + size_t out_len = 0; |
| 202 | + const size_t max_out_len = in.size(); // at most |in_len| bytes written |
| 203 | + auto buf = DataPointer::Alloc(max_out_len == 0 ? 1 : max_out_len); |
| 204 | + if (!EVP_AEAD_CTX_open(ctx.get(), |
| 205 | + static_cast<unsigned char*>(buf.get()), |
| 206 | + &out_len, |
| 207 | + max_out_len, |
| 208 | + iv_bytes, |
| 209 | + iv_len, |
| 210 | + in.data<unsigned char>(), |
| 211 | + in.size(), |
| 212 | + ad_bytes, |
| 213 | + ad_len)) { |
| 214 | + return WebCryptoCipherStatus::FAILED; |
| 215 | + } |
| 216 | + if (out_len == 0) { |
| 217 | + *out = ByteSource(); |
| 218 | + } else { |
| 219 | + buf = buf.resize(out_len); |
| 220 | + *out = ByteSource::Allocated(buf.release()); |
| 221 | + } |
| 222 | + return WebCryptoCipherStatus::OK; |
| 223 | +#else |
147 | 224 | auto ctx = CipherCtxPointer::New(); |
148 | 225 | CHECK(ctx); |
149 | 226 |
|
@@ -242,6 +319,7 @@ WebCryptoCipherStatus ChaCha20Poly1305CipherTraits::DoCipher( |
242 | 319 | *out = ByteSource::Allocated(buf.release()); |
243 | 320 |
|
244 | 321 | return WebCryptoCipherStatus::OK; |
| 322 | +#endif // OPENSSL_IS_BORINGSSL |
245 | 323 | } |
246 | 324 |
|
247 | 325 | void ChaCha20Poly1305::Initialize(Environment* env, Local<Object> target) { |
|
0 commit comments