Index: crypto/ec_signature_creator_nss.cc |
diff --git a/crypto/ec_signature_creator_nss.cc b/crypto/ec_signature_creator_nss.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3e3626f449982fba2171767d278fefffccdc88e2 |
--- /dev/null |
+++ b/crypto/ec_signature_creator_nss.cc |
@@ -0,0 +1,114 @@ |
+// 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 <cryptohi.h> |
+#include <pk11pub.h> |
+#include <secerr.h> |
+#include <sechash.h> |
+#if defined(OS_POSIX) |
+#include <unistd.h> |
+#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, |
+ size_t* out_signature_len) { |
+ 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<uint8> 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<unsigned int>(hash_data.size())}; |
+ |
+ // Compute signature of hash. |
+ int signature_len = PK11_SignatureLen(key); |
+ std::vector<uint8> signature_data(signature_len); |
+ SECItem sig = {siBuffer, &signature_data[0], |
+ static_cast<unsigned int>(signature_len)}; |
+ rv = PK11_Sign(key, &sig, &hash); |
+ if (rv != SECSuccess) |
+ return rv; |
+ |
+ *out_signature_len = sig.len; |
+ |
+ // DER encode the signature. |
+ return DSAU_EncodeDerSigWithLen(result, &sig, sig.len); |
+} |
+ |
+} // namespace |
+ |
+ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) |
+ : key_(key), |
+ signature_len_(0) { |
+ EnsureNSSInit(); |
+} |
+ |
+ECSignatureCreatorImpl::~ECSignatureCreatorImpl() {} |
+ |
+bool ECSignatureCreatorImpl::Sign(const uint8* data, |
+ int data_len, |
+ std::vector<uint8>* signature) { |
+ // Data to be signed |
+ SECItem secret; |
+ secret.type = siBuffer; |
+ secret.len = data_len; |
+ secret.data = const_cast<unsigned char*>(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, &signature_len_); |
+ 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<uint8>& der_sig, |
+ std::vector<uint8>* 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<uint8*>(&der_sig[0]); |
+ |
+ 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 |