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