signature_creator_nss.cc revision 24854748fba09df2a29f0d08d558c3acea70e7a1
1f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be 3f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// found in the LICENSE file. 4f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 5f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "crypto/signature_creator.h" 6f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 7f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <cryptohi.h> 8f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <keyhi.h> 924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko#include <stdint.h> 10f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <stdlib.h> 11f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 12f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/logging.h" 13f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/memory/scoped_ptr.h" 14f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "crypto/nss_util.h" 15f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "crypto/rsa_private_key.h" 16f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 17f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace crypto { 18f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 19f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace { 20f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 21f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoSECOidTag ToNSSSigOid(SignatureCreator::HashAlgorithm hash_alg) { 22f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko switch (hash_alg) { 23f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko case SignatureCreator::SHA1: 24f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; 25f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko case SignatureCreator::SHA256: 26f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; 27f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 28f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return SEC_OID_UNKNOWN; 29f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 30f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 31f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoSECOidTag ToNSSHashOid(SignatureCreator::HashAlgorithm hash_alg) { 32f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko switch (hash_alg) { 33f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko case SignatureCreator::SHA1: 34f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return SEC_OID_SHA1; 35f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko case SignatureCreator::SHA256: 36f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return SEC_OID_SHA256; 37f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 38f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return SEC_OID_UNKNOWN; 39f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 40f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 41f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} // namespace 42f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 43f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoSignatureCreator::~SignatureCreator() { 44f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (sign_context_) { 45f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SGN_DestroyContext(sign_context_, PR_TRUE); 46f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko sign_context_ = NULL; 47f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 48f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 49f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 50f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// static 51f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoSignatureCreator* SignatureCreator::Create(RSAPrivateKey* key, 52f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko HashAlgorithm hash_alg) { 53f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko scoped_ptr<SignatureCreator> result(new SignatureCreator); 54f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko result->sign_context_ = SGN_NewContext(ToNSSSigOid(hash_alg), key->key()); 55f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (!result->sign_context_) { 56f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko NOTREACHED(); 57f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return NULL; 58f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 59f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 60f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECStatus rv = SGN_Begin(result->sign_context_); 61f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (rv != SECSuccess) { 62f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko NOTREACHED(); 63f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return NULL; 64f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 65f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 66f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return result.release(); 67f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 68f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 69f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// static 70f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool SignatureCreator::Sign(RSAPrivateKey* key, 71f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko HashAlgorithm hash_alg, 7224854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko const uint8_t* data, 73f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko int data_len, 7424854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko std::vector<uint8_t>* signature) { 75f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECItem data_item; 76f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko data_item.type = siBuffer; 77f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko data_item.data = const_cast<unsigned char*>(data); 78f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko data_item.len = data_len; 79f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 80f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECItem signature_item; 81f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECStatus rv = SGN_Digest(key->key(), ToNSSHashOid(hash_alg), &signature_item, 82f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko &data_item); 83f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (rv != SECSuccess) { 84f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko NOTREACHED(); 85f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return false; 86f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 87f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko signature->assign(signature_item.data, 88f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko signature_item.data + signature_item.len); 89f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECITEM_FreeItem(&signature_item, PR_FALSE); 90f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return true; 91f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 92f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 9324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkobool SignatureCreator::Update(const uint8_t* data_part, int data_part_len) { 94f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECStatus rv = SGN_Update(sign_context_, data_part, data_part_len); 95f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (rv != SECSuccess) { 96f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko NOTREACHED(); 97f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return false; 98f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 99f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 100f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return true; 101f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 102f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 10324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkobool SignatureCreator::Final(std::vector<uint8_t>* signature) { 104f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECItem signature_item; 105f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECStatus rv = SGN_End(sign_context_, &signature_item); 106f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko if (rv != SECSuccess) { 107f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return false; 108f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko } 109f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko signature->assign(signature_item.data, 110f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko signature_item.data + signature_item.len); 111f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko SECITEM_FreeItem(&signature_item, PR_FALSE); 112f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko return true; 113f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 114f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 115f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoSignatureCreator::SignatureCreator() : sign_context_(NULL) { 116f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko EnsureNSSInit(); 117f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} 118f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko 119f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko} // namespace crypto 120