Home | History | Annotate | Download | only in openssl
      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
      3 // found in the LICENSE file.
      4 
      5 #include "content/child/webcrypto/openssl/util_openssl.h"
      6 
      7 #include <openssl/evp.h>
      8 
      9 #include "base/stl_util.h"
     10 #include "content/child/webcrypto/crypto_data.h"
     11 #include "content/child/webcrypto/openssl/key_openssl.h"
     12 #include "content/child/webcrypto/platform_crypto.h"
     13 #include "content/child/webcrypto/status.h"
     14 #include "crypto/openssl_util.h"
     15 
     16 namespace content {
     17 
     18 namespace webcrypto {
     19 
     20 void PlatformInit() {
     21   crypto::EnsureOpenSSLInit();
     22 }
     23 
     24 const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id) {
     25   switch (id) {
     26     case blink::WebCryptoAlgorithmIdSha1:
     27       return EVP_sha1();
     28     case blink::WebCryptoAlgorithmIdSha256:
     29       return EVP_sha256();
     30     case blink::WebCryptoAlgorithmIdSha384:
     31       return EVP_sha384();
     32     case blink::WebCryptoAlgorithmIdSha512:
     33       return EVP_sha512();
     34     default:
     35       return NULL;
     36   }
     37 }
     38 
     39 Status AeadEncryptDecrypt(EncryptOrDecrypt mode,
     40                           const std::vector<uint8_t>& raw_key,
     41                           const CryptoData& data,
     42                           unsigned int tag_length_bytes,
     43                           const CryptoData& iv,
     44                           const CryptoData& additional_data,
     45                           const EVP_AEAD* aead_alg,
     46                           std::vector<uint8_t>* buffer) {
     47   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
     48   EVP_AEAD_CTX ctx;
     49 
     50   if (!aead_alg)
     51     return Status::ErrorUnexpected();
     52 
     53   if (!EVP_AEAD_CTX_init(&ctx,
     54                          aead_alg,
     55                          vector_as_array(&raw_key),
     56                          raw_key.size(),
     57                          tag_length_bytes,
     58                          NULL)) {
     59     return Status::OperationError();
     60   }
     61 
     62   crypto::ScopedOpenSSL<EVP_AEAD_CTX, EVP_AEAD_CTX_cleanup>::Type ctx_cleanup(
     63       &ctx);
     64 
     65   size_t len;
     66   int ok;
     67 
     68   if (mode == DECRYPT) {
     69     if (data.byte_length() < tag_length_bytes)
     70       return Status::ErrorDataTooSmall();
     71 
     72     buffer->resize(data.byte_length() - tag_length_bytes);
     73 
     74     ok = EVP_AEAD_CTX_open(&ctx,
     75                            vector_as_array(buffer),
     76                            &len,
     77                            buffer->size(),
     78                            iv.bytes(),
     79                            iv.byte_length(),
     80                            data.bytes(),
     81                            data.byte_length(),
     82                            additional_data.bytes(),
     83                            additional_data.byte_length());
     84   } else {
     85     // No need to check for unsigned integer overflow here (seal fails if
     86     // the output buffer is too small).
     87     buffer->resize(data.byte_length() + EVP_AEAD_max_overhead(aead_alg));
     88 
     89     ok = EVP_AEAD_CTX_seal(&ctx,
     90                            vector_as_array(buffer),
     91                            &len,
     92                            buffer->size(),
     93                            iv.bytes(),
     94                            iv.byte_length(),
     95                            data.bytes(),
     96                            data.byte_length(),
     97                            additional_data.bytes(),
     98                            additional_data.byte_length());
     99   }
    100 
    101   if (!ok)
    102     return Status::OperationError();
    103   buffer->resize(len);
    104   return Status::Success();
    105 }
    106 
    107 }  // namespace webcrypto
    108 
    109 }  // namespace content
    110