| // Copyright (c) 2012 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 "crypto/signature_creator.h" | 
 |  | 
 | #include "base/logging.h" | 
 | #include "crypto/openssl_util.h" | 
 | #include "crypto/rsa_private_key.h" | 
 | #include "starboard/types.h" | 
 | #include "third_party/boringssl/src/include/openssl/evp.h" | 
 | #include "third_party/boringssl/src/include/openssl/rsa.h" | 
 |  | 
 | namespace crypto { | 
 |  | 
 | namespace { | 
 |  | 
 | const EVP_MD* ToOpenSSLDigest(SignatureCreator::HashAlgorithm hash_alg) { | 
 |   switch (hash_alg) { | 
 |     case SignatureCreator::SHA1: | 
 |       return EVP_sha1(); | 
 |     case SignatureCreator::SHA256: | 
 |       return EVP_sha256(); | 
 |   } | 
 |   return nullptr; | 
 | } | 
 |  | 
 | int ToOpenSSLDigestType(SignatureCreator::HashAlgorithm hash_alg) { | 
 |   switch (hash_alg) { | 
 |     case SignatureCreator::SHA1: | 
 |       return NID_sha1; | 
 |     case SignatureCreator::SHA256: | 
 |       return NID_sha256; | 
 |   } | 
 |   return NID_undef; | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | SignatureCreator::~SignatureCreator() { | 
 |   EVP_MD_CTX_destroy(sign_context_); | 
 | } | 
 |  | 
 | // static | 
 | std::unique_ptr<SignatureCreator> SignatureCreator::Create( | 
 |     RSAPrivateKey* key, | 
 |     HashAlgorithm hash_alg) { | 
 |   OpenSSLErrStackTracer err_tracer(FROM_HERE); | 
 |   std::unique_ptr<SignatureCreator> result(new SignatureCreator); | 
 |   const EVP_MD* const digest = ToOpenSSLDigest(hash_alg); | 
 |   DCHECK(digest); | 
 |   if (!digest) { | 
 |     return nullptr; | 
 |   } | 
 |   if (!EVP_DigestSignInit(result->sign_context_, nullptr, digest, nullptr, | 
 |                           key->key())) { | 
 |     return nullptr; | 
 |   } | 
 |   return result; | 
 | } | 
 |  | 
 | // static | 
 | bool SignatureCreator::Sign(RSAPrivateKey* key, | 
 |                             HashAlgorithm hash_alg, | 
 |                             const uint8_t* data, | 
 |                             int data_len, | 
 |                             std::vector<uint8_t>* signature) { | 
 |   bssl::UniquePtr<RSA> rsa_key(EVP_PKEY_get1_RSA(key->key())); | 
 |   if (!rsa_key) | 
 |     return false; | 
 |   signature->resize(RSA_size(rsa_key.get())); | 
 |  | 
 |   unsigned int len = 0; | 
 |   if (!RSA_sign(ToOpenSSLDigestType(hash_alg), data, data_len, | 
 |                 signature->data(), &len, rsa_key.get())) { | 
 |     signature->clear(); | 
 |     return false; | 
 |   } | 
 |   signature->resize(len); | 
 |   return true; | 
 | } | 
 |  | 
 | bool SignatureCreator::Update(const uint8_t* data_part, int data_part_len) { | 
 |   OpenSSLErrStackTracer err_tracer(FROM_HERE); | 
 |   return !!EVP_DigestSignUpdate(sign_context_, data_part, data_part_len); | 
 | } | 
 |  | 
 | bool SignatureCreator::Final(std::vector<uint8_t>* signature) { | 
 |   OpenSSLErrStackTracer err_tracer(FROM_HERE); | 
 |  | 
 |   // Determine the maximum length of the signature. | 
 |   size_t len = 0; | 
 |   if (!EVP_DigestSignFinal(sign_context_, nullptr, &len)) { | 
 |     signature->clear(); | 
 |     return false; | 
 |   } | 
 |   signature->resize(len); | 
 |  | 
 |   // Sign it. | 
 |   if (!EVP_DigestSignFinal(sign_context_, signature->data(), &len)) { | 
 |     signature->clear(); | 
 |     return false; | 
 |   } | 
 |   signature->resize(len); | 
 |   return true; | 
 | } | 
 |  | 
 | SignatureCreator::SignatureCreator() : sign_context_(EVP_MD_CTX_create()) {} | 
 |  | 
 | }  // namespace crypto |