// 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/ec_signature_creator_impl.h" #include #include #include #include #if defined(OS_POSIX) #include #include #include #endif #include "base/logging.h" #include "crypto/ec_private_key.h" #include "crypto/nss_util.h" #include "crypto/scoped_nss_types.h" namespace crypto { namespace { SECStatus SignData(SECItem* result, SECItem* input, SECKEYPrivateKey* key, HASH_HashType hash_type) { if (key->keyType != ecKey) { DLOG(FATAL) << "Should be using an EC key."; PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } // Hash the input. std::vector hash_data(HASH_ResultLen(hash_type)); SECStatus rv = HASH_HashBuf( hash_type, &hash_data[0], input->data, input->len); if (rv != SECSuccess) return rv; SECItem hash = {siBuffer, &hash_data[0], static_cast(hash_data.size())}; // Compute signature of hash. int signature_len = PK11_SignatureLen(key); std::vector signature_data(signature_len); SECItem sig = {siBuffer, &signature_data[0], static_cast(signature_len)}; rv = PK11_Sign(key, &sig, &hash); if (rv != SECSuccess) return rv; // DER encode the signature. return DSAU_EncodeDerSigWithLen(result, &sig, sig.len); } } // namespace ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) : key_(key) { EnsureNSSInit(); } ECSignatureCreatorImpl::~ECSignatureCreatorImpl() {} bool ECSignatureCreatorImpl::Sign(const uint8_t* data, int data_len, std::vector* signature) { // Data to be signed SECItem secret; secret.type = siBuffer; secret.len = data_len; secret.data = const_cast(data); // SECItem to receive the output buffer. SECItem result; result.type = siBuffer; result.len = 0; result.data = NULL; // Sign the secret data and save it to |result|. SECStatus rv = SignData(&result, &secret, key_->key(), HASH_AlgSHA256); if (rv != SECSuccess) { DLOG(ERROR) << "DerSignData: " << PORT_GetError(); return false; } // Copy the signed data into the output vector. signature->assign(result.data, result.data + result.len); SECITEM_FreeItem(&result, PR_FALSE /* only free |result.data| */); return true; } bool ECSignatureCreatorImpl::DecodeSignature( const std::vector& der_sig, std::vector* out_raw_sig) { SECItem der_sig_item; der_sig_item.type = siBuffer; der_sig_item.len = der_sig.size(); der_sig_item.data = const_cast(&der_sig[0]); size_t signature_len = SECKEY_SignatureLen(key_->public_key()); if (signature_len == 0) return false; SECItem* raw_sig = DSAU_DecodeDerSigToLen(&der_sig_item, signature_len); if (!raw_sig) return false; out_raw_sig->assign(raw_sig->data, raw_sig->data + raw_sig->len); SECITEM_FreeItem(raw_sig, PR_TRUE /* free SECItem structure itself. */); return true; } } // namespace crypto