blob: 8b6d7356e301b0fed93ebd5832e9eb94e6789191 [file] [log] [blame]
Paul Bakkerc7bb02b2013-09-15 14:54:56 +02001/*
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
Paul Bakker4606c732013-09-15 17:04:23 +020028#if defined(POLARSSL_PK_WRITE_C)
Paul Bakkerc7bb02b2013-09-15 14:54:56 +020029
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
Paul Bakkercff68422013-09-15 20:43:33 +020043#if defined(POLARSSL_PEM_WRITE_C)
Paul Bakker77e23fb2013-09-15 20:03:26 +020044#include "polarssl/pem.h"
Paul Bakkerc7bb02b2013-09-15 14:54:56 +020045#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 */
62static 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 ) );
72 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
73
Paul Bakkerb9cfaa02013-10-11 18:58:55 +020074 return( (int) len );
Paul Bakkerc7bb02b2013-09-15 14:54:56 +020075}
76#endif /* POLARSSL_RSA_C */
77
78#if defined(POLARSSL_ECP_C)
79/*
80 * EC public key is an EC point
81 */
82static 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,
90 POLARSSL_ECP_PF_UNCOMPRESSED,
91 &len, buf, sizeof( buf ) ) ) != 0 )
92 {
93 return( ret );
94 }
95
96 if( *p - start < (int) len )
97 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
98
99 *p -= len;
100 memcpy( *p, buf, len );
101
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200102 return( (int) len );
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200103}
104
105/*
106 * ECParameters ::= CHOICE {
107 * namedCurve OBJECT IDENTIFIER
108 * }
109 */
110static 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
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200123 return( (int) len );
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200124}
125#endif /* POLARSSL_ECP_C */
126
127int 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
143 return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
144
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200145 return( (int) len );
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200146}
147
148int 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 )
160 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
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 ) );
190 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
191
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200192 return( (int) len );
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200193}
194
195int 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 ) );
217 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
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 )
242 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
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,
251 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) );
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,
259 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
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 ) );
270 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
271 }
272 else
273#endif
274 return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
275
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200276 return( (int) len );
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200277}
278
Paul Bakkercff68422013-09-15 20:43:33 +0200279#if defined(POLARSSL_PEM_WRITE_C)
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200280
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
289int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size )
290{
291 int ret;
292 unsigned char output_buf[4096];
Paul Bakker77e23fb2013-09-15 20:03:26 +0200293 size_t olen = 0;
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200294
295 if( ( ret = pk_write_pubkey_der( key, output_buf,
Paul Bakker77e23fb2013-09-15 20:03:26 +0200296 sizeof(output_buf) ) ) < 0 )
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200297 {
298 return( ret );
299 }
300
Paul Bakker77e23fb2013-09-15 20:03:26 +0200301 if( ( ret = pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200302 output_buf + sizeof(output_buf) - ret,
Paul Bakker77e23fb2013-09-15 20:03:26 +0200303 ret, buf, size, &olen ) ) != 0 )
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200304 {
305 return( ret );
306 }
307
308 return( 0 );
309}
310
311int pk_write_key_pem( pk_context *key, unsigned char *buf, size_t size )
312{
313 int ret;
314 unsigned char output_buf[4096];
Paul Bakkerfcc17212013-10-11 09:36:52 +0200315 const char *begin, *end;
Paul Bakker77e23fb2013-09-15 20:03:26 +0200316 size_t olen = 0;
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200317
Paul Bakker77e23fb2013-09-15 20:03:26 +0200318 if( ( ret = pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200319 return( ret );
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200320
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
337 return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
338
Paul Bakker77e23fb2013-09-15 20:03:26 +0200339 if( ( ret = pem_write_buffer( begin, end,
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200340 output_buf + sizeof(output_buf) - ret,
Paul Bakker77e23fb2013-09-15 20:03:26 +0200341 ret, buf, size, &olen ) ) != 0 )
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200342 {
343 return( ret );
344 }
345
346 return( 0 );
347}
Paul Bakkercff68422013-09-15 20:43:33 +0200348#endif /* POLARSSL_PEM_WRITE_C */
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200349
Paul Bakker4606c732013-09-15 17:04:23 +0200350#endif /* POLARSSL_PK_WRITE_C */