|  | // 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 <cryptohi.h> | 
|  | #include <keyhi.h> | 
|  | #include <stdlib.h> | 
|  |  | 
|  | #include "base/logging.h" | 
|  | #include "base/memory/scoped_ptr.h" | 
|  | #include "crypto/nss_util.h" | 
|  | #include "crypto/rsa_private_key.h" | 
|  |  | 
|  | namespace crypto { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | SECOidTag ToNSSSigOid(SignatureCreator::HashAlgorithm hash_alg) { | 
|  | switch (hash_alg) { | 
|  | case SignatureCreator::SHA1: | 
|  | return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | 
|  | case SignatureCreator::SHA256: | 
|  | return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | 
|  | } | 
|  | return SEC_OID_UNKNOWN; | 
|  | } | 
|  |  | 
|  | SECOidTag ToNSSHashOid(SignatureCreator::HashAlgorithm hash_alg) { | 
|  | switch (hash_alg) { | 
|  | case SignatureCreator::SHA1: | 
|  | return SEC_OID_SHA1; | 
|  | case SignatureCreator::SHA256: | 
|  | return SEC_OID_SHA256; | 
|  | } | 
|  | return SEC_OID_UNKNOWN; | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | SignatureCreator::~SignatureCreator() { | 
|  | if (sign_context_) { | 
|  | SGN_DestroyContext(sign_context_, PR_TRUE); | 
|  | sign_context_ = NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | // static | 
|  | SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key, | 
|  | HashAlgorithm hash_alg) { | 
|  | scoped_ptr<SignatureCreator> result(new SignatureCreator); | 
|  | result->key_ = key; | 
|  |  | 
|  | result->sign_context_ = SGN_NewContext(ToNSSSigOid(hash_alg), key->key()); | 
|  | if (!result->sign_context_) { | 
|  | NOTREACHED(); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | SECStatus rv = SGN_Begin(result->sign_context_); | 
|  | if (rv != SECSuccess) { | 
|  | NOTREACHED(); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | return result.release(); | 
|  | } | 
|  |  | 
|  | // static | 
|  | bool SignatureCreator::Sign(RSAPrivateKey* key, | 
|  | HashAlgorithm hash_alg, | 
|  | const uint8* data, | 
|  | int data_len, | 
|  | std::vector<uint8>* signature) { | 
|  | SECItem data_item; | 
|  | data_item.type = siBuffer; | 
|  | data_item.data = const_cast<unsigned char*>(data); | 
|  | data_item.len = data_len; | 
|  |  | 
|  | SECItem signature_item; | 
|  | SECStatus rv = SGN_Digest(key->key(), ToNSSHashOid(hash_alg), &signature_item, | 
|  | &data_item); | 
|  | if (rv != SECSuccess) { | 
|  | NOTREACHED(); | 
|  | return false; | 
|  | } | 
|  | signature->assign(signature_item.data, | 
|  | signature_item.data + signature_item.len); | 
|  | SECITEM_FreeItem(&signature_item, PR_FALSE); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { | 
|  | SECStatus rv = SGN_Update(sign_context_, data_part, data_part_len); | 
|  | if (rv != SECSuccess) { | 
|  | NOTREACHED(); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool SignatureCreator::Final(std::vector<uint8>* signature) { | 
|  | SECItem signature_item; | 
|  | SECStatus rv = SGN_End(sign_context_, &signature_item); | 
|  | if (rv != SECSuccess) { | 
|  | return false; | 
|  | } | 
|  | signature->assign(signature_item.data, | 
|  | signature_item.data + signature_item.len); | 
|  | SECITEM_FreeItem(&signature_item, PR_FALSE); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | SignatureCreator::SignatureCreator() | 
|  | : key_(NULL), | 
|  | sign_context_(NULL) { | 
|  | EnsureNSSInit(); | 
|  | } | 
|  |  | 
|  | }  // namespace crypto |