PolarSSL v1.3.7
pkwrite.c
Go to the documentation of this file.
1 /*
2  * Public Key layer for writing key files and structures
3  *
4  * Copyright (C) 2006-2014, Brainspark B.V.
5  *
6  * This file is part of PolarSSL (http://www.polarssl.org)
7  * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8  *
9  * All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 
26 #if !defined(POLARSSL_CONFIG_FILE)
27 #include "polarssl/config.h"
28 #else
29 #include POLARSSL_CONFIG_FILE
30 #endif
31 
32 #if defined(POLARSSL_PK_WRITE_C)
33 
34 #include "polarssl/pk.h"
35 #include "polarssl/asn1write.h"
36 #include "polarssl/oid.h"
37 
38 #if defined(POLARSSL_RSA_C)
39 #include "polarssl/rsa.h"
40 #endif
41 #if defined(POLARSSL_ECP_C)
42 #include "polarssl/ecp.h"
43 #endif
44 #if defined(POLARSSL_ECDSA_C)
45 #include "polarssl/ecdsa.h"
46 #endif
47 #if defined(POLARSSL_PEM_WRITE_C)
48 #include "polarssl/pem.h"
49 #endif
50 
51 #if defined(POLARSSL_PLATFORM_C)
52 #include "polarssl/platform.h"
53 #else
54 #include <stdlib.h>
55 #define polarssl_malloc malloc
56 #define polarssl_free free
57 #endif
58 
59 #if defined(POLARSSL_RSA_C)
60 /*
61  * RSAPublicKey ::= SEQUENCE {
62  * modulus INTEGER, -- n
63  * publicExponent INTEGER -- e
64  * }
65  */
66 static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
67  rsa_context *rsa )
68 {
69  int ret;
70  size_t len = 0;
71 
72  ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
73  ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
74 
75  ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
77  ASN1_SEQUENCE ) );
78 
79  return( (int) len );
80 }
81 #endif /* POLARSSL_RSA_C */
82 
83 #if defined(POLARSSL_ECP_C)
84 /*
85  * EC public key is an EC point
86  */
87 static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
88  ecp_keypair *ec )
89 {
90  int ret;
91  size_t len = 0;
92  unsigned char buf[POLARSSL_ECP_MAX_PT_LEN];
93 
94  if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q,
96  &len, buf, sizeof( buf ) ) ) != 0 )
97  {
98  return( ret );
99  }
100 
101  if( *p - start < (int) len )
103 
104  *p -= len;
105  memcpy( *p, buf, len );
106 
107  return( (int) len );
108 }
109 
110 /*
111  * ECParameters ::= CHOICE {
112  * namedCurve OBJECT IDENTIFIER
113  * }
114  */
115 static int pk_write_ec_param( unsigned char **p, unsigned char *start,
116  ecp_keypair *ec )
117 {
118  int ret;
119  size_t len = 0;
120  const char *oid;
121  size_t oid_len;
122 
123  if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
124  return( ret );
125 
126  ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
127 
128  return( (int) len );
129 }
130 #endif /* POLARSSL_ECP_C */
131 
132 int pk_write_pubkey( unsigned char **p, unsigned char *start,
133  const pk_context *key )
134 {
135  int ret;
136  size_t len = 0;
137 
138 #if defined(POLARSSL_RSA_C)
139  if( pk_get_type( key ) == POLARSSL_PK_RSA )
140  ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, pk_rsa( *key ) ) );
141  else
142 #endif
143 #if defined(POLARSSL_ECP_C)
144  if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
145  ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, pk_ec( *key ) ) );
146  else
147 #endif
149 
150  return( (int) len );
151 }
152 
153 int pk_write_pubkey_der( pk_context *key, unsigned char *buf, size_t size )
154 {
155  int ret;
156  unsigned char *c;
157  size_t len = 0, par_len = 0, oid_len;
158  const char *oid;
159 
160  c = buf + size;
161 
162  ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, key ) );
163 
164  if( c - buf < 1 )
166 
167  /*
168  * SubjectPublicKeyInfo ::= SEQUENCE {
169  * algorithm AlgorithmIdentifier,
170  * subjectPublicKey BIT STRING }
171  */
172  *--c = 0;
173  len += 1;
174 
175  ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
176  ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
177 
178  if( ( ret = oid_get_oid_by_pk_alg( pk_get_type( key ),
179  &oid, &oid_len ) ) != 0 )
180  {
181  return( ret );
182  }
183 
184 #if defined(POLARSSL_ECP_C)
185  if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
186  {
187  ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, pk_ec( *key ) ) );
188  }
189 #endif
190 
191  ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
192  par_len ) );
193 
194  ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
196  ASN1_SEQUENCE ) );
197 
198  return( (int) len );
199 }
200 
201 int pk_write_key_der( pk_context *key, unsigned char *buf, size_t size )
202 {
203  int ret;
204  unsigned char *c = buf + size;
205  size_t len = 0;
206 
207 #if defined(POLARSSL_RSA_C)
208  if( pk_get_type( key ) == POLARSSL_PK_RSA )
209  {
210  rsa_context *rsa = pk_rsa( *key );
211 
212  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
213  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
214  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
215  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
216  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
217  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
218  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
219  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
220  ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
221 
222  ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
224  ASN1_SEQUENCE ) );
225  }
226  else
227 #endif /* POLARSSL_RSA_C */
228 #if defined(POLARSSL_ECP_C)
229  if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
230  {
231  ecp_keypair *ec = pk_ec( *key );
232  size_t pub_len = 0, par_len = 0;
233 
234  /*
235  * RFC 5915, or SEC1 Appendix C.4
236  *
237  * ECPrivateKey ::= SEQUENCE {
238  * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
239  * privateKey OCTET STRING,
240  * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
241  * publicKey [1] BIT STRING OPTIONAL
242  * }
243  */
244 
245  /* publicKey */
246  ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
247 
248  if( c - buf < 1 )
250  *--c = 0;
251  pub_len += 1;
252 
253  ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
254  ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
255 
256  ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
257  ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf,
259  len += pub_len;
260 
261  /* parameters */
262  ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
263 
264  ASN1_CHK_ADD( par_len, asn1_write_len( &c, buf, par_len ) );
265  ASN1_CHK_ADD( par_len, asn1_write_tag( &c, buf,
267  len += par_len;
268 
269  /* privateKey: write as MPI then fix tag */
270  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &ec->d ) );
271  *c = ASN1_OCTET_STRING;
272 
273  /* version */
274  ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) );
275 
276  ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
278  ASN1_SEQUENCE ) );
279  }
280  else
281 #endif /* POLARSSL_ECP_C */
283 
284  return( (int) len );
285 }
286 
287 #if defined(POLARSSL_PEM_WRITE_C)
288 
289 #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
290 #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
291 
292 #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n"
293 #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n"
294 #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n"
295 #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n"
296 
297 int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size )
298 {
299  int ret;
300  unsigned char output_buf[4096];
301  size_t olen = 0;
302 
303  if( ( ret = pk_write_pubkey_der( key, output_buf,
304  sizeof(output_buf) ) ) < 0 )
305  {
306  return( ret );
307  }
308 
309  if( ( ret = pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
310  output_buf + sizeof(output_buf) - ret,
311  ret, buf, size, &olen ) ) != 0 )
312  {
313  return( ret );
314  }
315 
316  return( 0 );
317 }
318 
319 int pk_write_key_pem( pk_context *key, unsigned char *buf, size_t size )
320 {
321  int ret;
322  unsigned char output_buf[4096];
323  const char *begin, *end;
324  size_t olen = 0;
325 
326  if( ( ret = pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
327  return( ret );
328 
329 #if defined(POLARSSL_RSA_C)
330  if( pk_get_type( key ) == POLARSSL_PK_RSA )
331  {
332  begin = PEM_BEGIN_PRIVATE_KEY_RSA;
333  end = PEM_END_PRIVATE_KEY_RSA;
334  }
335  else
336 #endif
337 #if defined(POLARSSL_ECP_C)
338  if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
339  {
340  begin = PEM_BEGIN_PRIVATE_KEY_EC;
341  end = PEM_END_PRIVATE_KEY_EC;
342  }
343  else
344 #endif
346 
347  if( ( ret = pem_write_buffer( begin, end,
348  output_buf + sizeof(output_buf) - ret,
349  ret, buf, size, &olen ) ) != 0 )
350  {
351  return( ret );
352  }
353 
354  return( 0 );
355 }
356 #endif /* POLARSSL_PEM_WRITE_C */
357 
358 #endif /* POLARSSL_PK_WRITE_C */
int pk_write_key_der(pk_context *ctx, unsigned char *buf, size_t size)
Write a private key to a PKCS#1 or SEC1 DER structure Note: data is written at the end of the buffer!...
int oid_get_oid_by_ec_grp(ecp_group_id grp_id, const char **oid, size_t *olen)
Translate EC group identifier into NamedCurve OID.
Elliptic curves over GF(p)
int pk_write_key_pem(pk_context *ctx, unsigned char *buf, size_t size)
Write a private key to a PKCS#1 or SEC1 PEM string.
Elliptic curve DSA.
ecp_group grp
Definition: ecp.h:165
#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL
Buffer too small when writing ASN.1 data structure.
Definition: asn1.h:60
int oid_get_oid_by_pk_alg(pk_type_t pk_alg, const char **oid, size_t *olen)
Translate pk_type into PublicKeyAlgorithm OID.
#define ASN1_SEQUENCE
Definition: asn1.h:82
#define POLARSSL_ECP_PF_UNCOMPRESSED
Uncompressed point format.
Definition: ecp.h:233
mpi DQ
Definition: rsa.h:93
Configuration options (set of defines)
#define ASN1_CONSTRUCTED
Definition: asn1.h:92
ECP key pair structure.
Definition: ecp.h:163
mpi d
Definition: ecp.h:166
PolarSSL Platform abstraction layer.
#define pk_ec(pk)
Quick access to an EC context inside a PK context.
Definition: pk.h:84
pk_type_t pk_get_type(const pk_context *ctx)
Get the key type.
Object Identifier (OID) database.
Public Key abstraction layer.
int asn1_write_len(unsigned char **p, unsigned char *start, size_t len)
Write a length field in ASN.1 format Note: function works backwards in data buffer.
mpi P
Definition: rsa.h:90
mpi Q
Definition: rsa.h:91
#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE
Unavailable feature, e.g.
Definition: pk.h:63
int pk_write_pubkey(unsigned char **p, unsigned char *start, const pk_context *key)
Write a subjectPublicKey to ASN.1 data Note: function works backwards in data buffer.
int pk_write_pubkey_der(pk_context *ctx, unsigned char *buf, size_t size)
Write a public key to a SubjectPublicKeyInfo DER structure Note: data is written at the end of the bu...
RSA context structure.
Definition: rsa.h:81
mpi D
Definition: rsa.h:89
ecp_group_id id
Definition: ecp.h:138
mpi QP
Definition: rsa.h:94
Privacy Enhanced Mail (PEM) decoding.
#define POLARSSL_ECP_MAX_PT_LEN
Definition: ecp.h:187
mpi N
Definition: rsa.h:86
mpi E
Definition: rsa.h:87
mpi DP
Definition: rsa.h:92
#define ASN1_BIT_STRING
Definition: asn1.h:77
#define ASN1_CONTEXT_SPECIFIC
Definition: asn1.h:93
int asn1_write_mpi(unsigned char **p, unsigned char *start, mpi *X)
Write a big number (ASN1_INTEGER) in ASN.1 format Note: function works backwards in data buffer...
int asn1_write_int(unsigned char **p, unsigned char *start, int val)
Write an int tag (ASN1_INTEGER) and value in ASN.1 format Note: function works backwards in data buff...
The RSA public-key cryptosystem.
int ecp_point_write_binary(const ecp_group *grp, const ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen)
Export a point into unsigned binary data.
#define pk_rsa(pk)
Quick access to an RSA context inside a PK context.
Definition: pk.h:74
#define ASN1_CHK_ADD(g, f)
Definition: asn1write.h:32
int asn1_write_algorithm_identifier(unsigned char **p, unsigned char *start, const char *oid, size_t oid_len, size_t par_len)
Write an AlgorithmIdentifier sequence in ASN.1 format Note: function works backwards in data buffer...
ASN.1 buffer writing functionality.
ecp_point Q
Definition: ecp.h:167
int asn1_write_oid(unsigned char **p, unsigned char *start, const char *oid, size_t oid_len)
Write an OID tag (ASN1_OID) and data in ASN.1 format Note: function works backwards in data buffer...
#define ASN1_OCTET_STRING
Definition: asn1.h:78
int pk_write_pubkey_pem(pk_context *ctx, unsigned char *buf, size_t size)
Write a public key to a PEM string.
int asn1_write_tag(unsigned char **p, unsigned char *start, unsigned char tag)
Write a ASN.1 tag in ASN.1 format Note: function works backwards in data buffer.
Public key container.
Definition: pk.h:182