1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/rsa_private_key.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <list>
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/cssm_init.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace crypto {
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottRSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_CC_HANDLE cc_handle;
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_RETURN crtn;
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  crtn = CSSM_CSP_CreateKeyGenContext(GetSharedCSPHandle(), CSSM_ALGID_RSA,
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      num_bits, NULL, NULL, NULL, NULL, NULL,
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      &cc_handle);
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (crtn) {
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn;
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_DATA label = { 9,
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const_cast<uint8*>(reinterpret_cast<const uint8*>("temp_key")) };
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  crtn = CSSM_GenerateKeyPair(cc_handle,
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CSSM_KEYUSE_VERIFY,
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label,
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      result->public_key(), CSSM_KEYUSE_SIGN,
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, NULL,
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result->key());
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_DeleteContext(cc_handle);
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (crtn) {
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn;
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result.release();
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickRSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) {
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NOTIMPLEMENTED();
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return NULL;
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottRSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::vector<uint8>& input) {
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (input.empty())
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_KEY key;
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(&key, 0, sizeof(key));
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyData.Data = const_cast<uint8*>(&input.front());
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyData.Length = input.size();
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyHeader.AlgorithmId = CSSM_ALGID_RSA;
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyHeader.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyHeader.KeyUsage = CSSM_KEYUSE_ANY;
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_KEY_SIZE key_size;
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_RETURN crtn;
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  crtn = CSSM_QueryKeySizeInBits(GetSharedCSPHandle(), NULL, &key, &key_size);
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (crtn) {
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn;
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Perform a NULL unwrap operation on the key so that result's key_
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // instance variable points to a key that can be released via CSSM_FreeKey().
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_ACCESS_CREDENTIALS creds;
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_CC_HANDLE cc_handle;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  crtn = CSSM_CSP_CreateSymmetricContext(GetSharedCSPHandle(), CSSM_ALGID_NONE,
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CSSM_ALGMODE_NONE, &creds, NULL, NULL, CSSM_PADDING_NONE, 0, &cc_handle);
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (crtn) {
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED() << "CSSM_CSP_CreateSymmetricContext failed: " << crtn;
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CSSM_DATA label_data, desc_data = { 0, NULL };
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  label_data.Data =
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const_cast<uint8*>(reinterpret_cast<const uint8*>("unwrapped"));
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  label_data.Length = 9;
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  crtn = CSSM_UnwrapKey(cc_handle, NULL, &key, CSSM_KEYUSE_ANY,
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label_data,
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NULL, result->key(), &desc_data);
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (crtn) {
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED() << "CSSM_UnwrapKey failed: " << crtn;
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Extract a public key from the private key.
10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Apple doesn't accept CSSM_KEYBLOB_RAW_FORMAT_X509 as a valid key
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // format when attempting to generate certs, so use PKCS1 instead.
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  PrivateKeyInfoCodec codec(true);
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::vector<uint8> private_key_data;
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  private_key_data.assign(key.KeyData.Data,
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                          key.KeyData.Data + key.KeyData.Length);
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!codec.Import(private_key_data)) {
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return NULL;
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::vector<uint8> public_key_data;
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!codec.ExportPublicKey(&public_key_data)) {
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return NULL;
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CSSM_KEY* public_key = result->public_key();
12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  size_t size = public_key_data.size();
12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyData.Data = reinterpret_cast<uint8*>(CSSMMalloc(size));
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!public_key->KeyData.Data) {
12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED() << "CSSMMalloc failed";
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return NULL;
12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  memcpy(public_key->KeyData.Data, &public_key_data.front(), size);
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyData.Length = size;
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyHeader.AlgorithmId = CSSM_ALGID_RSA;
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY;
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crtn = CSSM_QueryKeySizeInBits(GetSharedCSPHandle(), NULL, public_key,
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 &key_size);
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (crtn) {
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DLOG(ERROR) << "CSSM_QueryKeySizeInBits failed " << crtn;
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return NULL;
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  public_key->KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result.release();
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickRSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::vector<uint8>& input) {
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NOTIMPLEMENTED();
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return NULL;
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickRSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::vector<uint8>& input) {
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NOTIMPLEMENTED();
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return NULL;
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochRSAPrivateKey::RSAPrivateKey() {
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(&key_, 0, sizeof(key_));
16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  memset(&public_key_, 0, sizeof(public_key_));
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EnsureCSSMInit();
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottRSAPrivateKey::~RSAPrivateKey() {
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (key_.KeyData.Data) {
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CSSM_FreeKey(GetSharedCSPHandle(), NULL, &key_, CSSM_FALSE);
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (public_key_.KeyData.Data) {
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    CSSM_FreeKey(GetSharedCSPHandle(), NULL, &public_key_, CSSM_FALSE);
17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) {
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!key_.KeyData.Data || !key_.KeyData.Length) {
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  output->clear();
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  output->insert(output->end(), key_.KeyData.Data,
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                key_.KeyData.Data + key_.KeyData.Length);
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) {
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PrivateKeyInfoCodec private_key_info(true);
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::vector<uint8> private_key_data;
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  private_key_data.assign(key_.KeyData.Data,
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          key_.KeyData.Data + key_.KeyData.Length);
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return (private_key_info.Import(private_key_data) &&
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          private_key_info.ExportPublicKeyInfo(output));
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}  // namespace crypto
197