PolarSSL v1.3.1
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-2013, 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 #include "polarssl/config.h"
27 
28 #if defined(POLARSSL_PK_WRITE_C)
29 
30 #include "polarssl/pk.h"
31 #include "polarssl/asn1write.h"
32 #include "polarssl/oid.h"
33 
34 #if defined(POLARSSL_RSA_C)
35 #include "polarssl/rsa.h"
36 #endif
37 #if defined(POLARSSL_ECP_C)
38 #include "polarssl/ecp.h"
39 #endif
40 #if defined(POLARSSL_ECDSA_C)
41 #include "polarssl/ecdsa.h"
42 #endif
43 #if defined(POLARSSL_PEM_WRITE_C)
44 #include "polarssl/pem.h"
45 #endif
46 
47 #if defined(POLARSSL_MEMORY_C)
48 #include "polarssl/memory.h"
49 #else
50 #include <stdlib.h>
51 #define polarssl_malloc malloc
52 #define polarssl_free free
53 #endif
54 
55 #if defined(POLARSSL_RSA_C)
56 /*
57  * RSAPublicKey ::= SEQUENCE {
58  * modulus INTEGER, -- n
59  * publicExponent INTEGER -- e
60  * }
61  */
62 static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
63  rsa_context *rsa )
64 {
65  int ret;
66  size_t len = 0;
67 
68  ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
69  ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
70 
71  ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
73 
74  return( (int) len );
75 }
76 #endif /* POLARSSL_RSA_C */
77 
78 #if defined(POLARSSL_ECP_C)
79 /*
80  * EC public key is an EC point
81  */
82 static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
83  ecp_keypair *ec )
84 {
85  int ret;
86  size_t len = 0;
87  unsigned char buf[POLARSSL_ECP_MAX_PT_LEN];
88 
89  if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q,
91  &len, buf, sizeof( buf ) ) ) != 0 )
92  {
93  return( ret );
94  }
95 
96  if( *p - start < (int) len )
98 
99  *p -= len;
100  memcpy( *p, buf, len );
101 
102  return( (int) len );
103 }
104 
105 /*
106  * ECParameters ::= CHOICE {
107  * namedCurve OBJECT IDENTIFIER
108  * }
109  */
110 static int pk_write_ec_param( unsigned char **p, unsigned char *start,
111  ecp_keypair *ec )
112 {
113  int ret;
114  size_t len = 0;
115  const char *oid;
116  size_t oid_len;
117 
118  if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
119  return( ret );
120 
121  ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
122 
123  return( (int) len );
124 }
125 #endif /* POLARSSL_ECP_C */
126 
127 int pk_write_pubkey( unsigned char **p, unsigned char *start,
128  const pk_context *key )
129 {
130  int ret;
131  size_t len = 0;
132 
133 #if defined(POLARSSL_RSA_C)
134  if( pk_get_type( key ) == POLARSSL_PK_RSA )
135  ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, pk_rsa( *key ) ) );
136  else
137 #endif
138 #if defined(POLARSSL_ECP_C)
139  if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
140  ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, pk_ec( *key ) ) );
141  else
142 #endif
144 
145  return( (int) len );
146 }
147 
148 int pk_write_pubkey_der( pk_context *key, unsigned char *buf, size_t size )
149 {
150  int ret;
151  unsigned char *c;
152  size_t len = 0, par_len = 0, oid_len;
153  const char *oid;
154 
155  c = buf + size;
156 
157  ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, key ) );
158 
159  if( c - buf < 1 )
161 
162  /*
163  * SubjectPublicKeyInfo ::= SEQUENCE {
164  * algorithm AlgorithmIdentifier,
165  * subjectPublicKey BIT STRING }
166  */
167  *--c = 0;
168  len += 1;
169 
170  ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
171  ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
172 
173  if( ( ret = oid_get_oid_by_pk_alg( pk_get_type( key ),
174  &oid, &oid_len ) ) != 0 )
175  {
176  return( ret );
177  }
178 
179 #if defined(POLARSSL_ECP_C)
180  if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
181  {
182  ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, pk_ec( *key ) ) );
183  }
184 #endif
185 
186  ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
187  par_len ) );
188 
189  ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
191 
192  return( (int) len );
193 }
194 
195 int pk_write_key_der( pk_context *key, unsigned char *buf, size_t size )
196 {
197  int ret;
198  unsigned char *c = buf + size;
199  size_t len = 0;
200 
201 #if defined(POLARSSL_RSA_C)
202  if( pk_get_type( key ) == POLARSSL_PK_RSA )
203  {
204  rsa_context *rsa = pk_rsa( *key );
205 
206  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
207  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
208  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
209  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
210  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
211  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
212  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
213  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
214  ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
215 
216  ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
218  }
219  else
220 #endif
221 #if defined(POLARSSL_ECP_C)
222  if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
223  {
224  ecp_keypair *ec = pk_ec( *key );
225  size_t pub_len = 0, par_len = 0;
226 
227  /*
228  * RFC 5915, or SEC1 Appendix C.4
229  *
230  * ECPrivateKey ::= SEQUENCE {
231  * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
232  * privateKey OCTET STRING,
233  * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
234  * publicKey [1] BIT STRING OPTIONAL
235  * }
236  */
237 
238  /* publicKey */
239  ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
240 
241  if( c - buf < 1 )
243  *--c = 0;
244  pub_len += 1;
245 
246  ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
247  ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
248 
249  ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
250  ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf,
252  len += pub_len;
253 
254  /* parameters */
255  ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
256 
257  ASN1_CHK_ADD( par_len, asn1_write_len( &c, buf, par_len ) );
258  ASN1_CHK_ADD( par_len, asn1_write_tag( &c, buf,
260  len += par_len;
261 
262  /* privateKey: write as MPI then fix tag */
263  ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &ec->d ) );
264  *c = ASN1_OCTET_STRING;
265 
266  /* version */
267  ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) );
268 
269  ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
271  }
272  else
273 #endif
275 
276  return( (int) len );
277 }
278 
279 #if defined(POLARSSL_PEM_WRITE_C)
280 
281 #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
282 #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
283 
284 #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n"
285 #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n"
286 #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n"
287 #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n"
288 
289 int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size )
290 {
291  int ret;
292  unsigned char output_buf[4096];
293  size_t olen = 0;
294 
295  if( ( ret = pk_write_pubkey_der( key, output_buf,
296  sizeof(output_buf) ) ) < 0 )
297  {
298  return( ret );
299  }
300 
301  if( ( ret = pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
302  output_buf + sizeof(output_buf) - ret,
303  ret, buf, size, &olen ) ) != 0 )
304  {
305  return( ret );
306  }
307 
308  return( 0 );
309 }
310 
311 int pk_write_key_pem( pk_context *key, unsigned char *buf, size_t size )
312 {
313  int ret;
314  unsigned char output_buf[4096];
315  const char *begin, *end;
316  size_t olen = 0;
317 
318  if( ( ret = pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
319  return( ret );
320 
321 #if defined(POLARSSL_RSA_C)
322  if( pk_get_type( key ) == POLARSSL_PK_RSA )
323  {
324  begin = PEM_BEGIN_PRIVATE_KEY_RSA;
325  end = PEM_END_PRIVATE_KEY_RSA;
326  }
327  else
328 #endif
329 #if defined(POLARSSL_ECP_C)
330  if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
331  {
332  begin = PEM_BEGIN_PRIVATE_KEY_EC;
333  end = PEM_END_PRIVATE_KEY_EC;
334  }
335  else
336 #endif
338 
339  if( ( ret = pem_write_buffer( begin, end,
340  output_buf + sizeof(output_buf) - ret,
341  ret, buf, size, &olen ) ) != 0 )
342  {
343  return( ret );
344  }
345 
346  return( 0 );
347 }
348 #endif /* POLARSSL_PEM_WRITE_C */
349 
350 #endif /* POLARSSL_PK_WRITE_C */