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