15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/ec_signature_creator_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <openssl/bn.h>
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <openssl/ec.h>
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <openssl/ecdsa.h>
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <openssl/evp.h>
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <openssl/sha.h>
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "crypto/ec_private_key.h"
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "crypto/openssl_util.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crypto/scoped_openssl_types.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace crypto {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace {
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtypedef ScopedOpenSSL<ECDSA_SIG, ECDSA_SIG_free>::Type ScopedECDSA_SIG;
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key)
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : key_(key), signature_len_(0) {
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EnsureOpenSSLInit();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ECSignatureCreatorImpl::~ECSignatureCreatorImpl() {}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ECSignatureCreatorImpl::Sign(const uint8* data,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int data_len,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  std::vector<uint8>* signature) {
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  OpenSSLErrStackTracer err_tracer(FROM_HERE);
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  size_t sig_len = 0;
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!ctx.get() ||
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      !EVP_DigestSignInit(ctx.get(), NULL, EVP_sha256(), NULL, key_->key()) ||
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      !EVP_DigestSignUpdate(ctx.get(), data, data_len) ||
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) {
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  signature->resize(sig_len);
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!EVP_DigestSignFinal(ctx.get(), &signature->front(), &sig_len))
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // NOTE: A call to EVP_DigestSignFinal() with a NULL second parameter returns
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // a maximum allocation size, while the call without a NULL returns the real
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // one, which may be smaller.
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  signature->resize(sig_len);
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ECSignatureCreatorImpl::DecodeSignature(const std::vector<uint8>& der_sig,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             std::vector<uint8>* out_raw_sig) {
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  OpenSSLErrStackTracer err_tracer(FROM_HERE);
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Create ECDSA_SIG object from DER-encoded data.
611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const unsigned char* der_data = &der_sig.front();
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedECDSA_SIG ecdsa_sig(
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      d2i_ECDSA_SIG(NULL, &der_data, static_cast<long>(der_sig.size())));
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!ecdsa_sig.get())
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The result is made of two 32-byte vectors.
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const size_t kMaxBytesPerBN = 32;
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<uint8> result;
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  result.resize(2 * kMaxBytesPerBN);
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  memset(&result[0], 0, result.size());
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BIGNUM* r = ecdsa_sig.get()->r;
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BIGNUM* s = ecdsa_sig.get()->s;
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int r_bytes = BN_num_bytes(r);
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int s_bytes = BN_num_bytes(s);
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // NOTE: Can't really check for equality here since sometimes the value
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // returned by BN_num_bytes() will be slightly smaller than kMaxBytesPerBN.
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (r_bytes > static_cast<int>(kMaxBytesPerBN) ||
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      s_bytes > static_cast<int>(kMaxBytesPerBN)) {
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DLOG(ERROR) << "Invalid key sizes r(" << r_bytes << ") s(" << s_bytes
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                << ")";
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BN_bn2bin(ecdsa_sig.get()->r, &result[kMaxBytesPerBN - r_bytes]);
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BN_bn2bin(ecdsa_sig.get()->s, &result[2 * kMaxBytesPerBN - s_bytes]);
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  out_raw_sig->swap(result);
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace crypto
92