mbed TLS library
Dependents: HTTPClient-SSL WS_SERVER
polarssl/pkwrite.c@0:137634ff4186, 2015-06-11 (annotated)
- Committer:
- ansond
- Date:
- Thu Jun 11 03:27:03 2015 +0000
- Revision:
- 0:137634ff4186
initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ansond | 0:137634ff4186 | 1 | /* |
ansond | 0:137634ff4186 | 2 | * Public Key layer for writing key files and structures |
ansond | 0:137634ff4186 | 3 | * |
ansond | 0:137634ff4186 | 4 | * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved |
ansond | 0:137634ff4186 | 5 | * |
ansond | 0:137634ff4186 | 6 | * This file is part of mbed TLS (https://tls.mbed.org) |
ansond | 0:137634ff4186 | 7 | * |
ansond | 0:137634ff4186 | 8 | * This program is free software; you can redistribute it and/or modify |
ansond | 0:137634ff4186 | 9 | * it under the terms of the GNU General Public License as published by |
ansond | 0:137634ff4186 | 10 | * the Free Software Foundation; either version 2 of the License, or |
ansond | 0:137634ff4186 | 11 | * (at your option) any later version. |
ansond | 0:137634ff4186 | 12 | * |
ansond | 0:137634ff4186 | 13 | * This program is distributed in the hope that it will be useful, |
ansond | 0:137634ff4186 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
ansond | 0:137634ff4186 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
ansond | 0:137634ff4186 | 16 | * GNU General Public License for more details. |
ansond | 0:137634ff4186 | 17 | * |
ansond | 0:137634ff4186 | 18 | * You should have received a copy of the GNU General Public License along |
ansond | 0:137634ff4186 | 19 | * with this program; if not, write to the Free Software Foundation, Inc., |
ansond | 0:137634ff4186 | 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
ansond | 0:137634ff4186 | 21 | */ |
ansond | 0:137634ff4186 | 22 | |
ansond | 0:137634ff4186 | 23 | #if !defined(POLARSSL_CONFIG_FILE) |
ansond | 0:137634ff4186 | 24 | #include "polarssl/config.h" |
ansond | 0:137634ff4186 | 25 | #else |
ansond | 0:137634ff4186 | 26 | #include POLARSSL_CONFIG_FILE |
ansond | 0:137634ff4186 | 27 | #endif |
ansond | 0:137634ff4186 | 28 | |
ansond | 0:137634ff4186 | 29 | #if defined(POLARSSL_PK_WRITE_C) |
ansond | 0:137634ff4186 | 30 | |
ansond | 0:137634ff4186 | 31 | #include "polarssl/pk.h" |
ansond | 0:137634ff4186 | 32 | #include "polarssl/asn1write.h" |
ansond | 0:137634ff4186 | 33 | #include "polarssl/oid.h" |
ansond | 0:137634ff4186 | 34 | |
ansond | 0:137634ff4186 | 35 | #include <string.h> |
ansond | 0:137634ff4186 | 36 | |
ansond | 0:137634ff4186 | 37 | #if defined(POLARSSL_RSA_C) |
ansond | 0:137634ff4186 | 38 | #include "polarssl/rsa.h" |
ansond | 0:137634ff4186 | 39 | #endif |
ansond | 0:137634ff4186 | 40 | #if defined(POLARSSL_ECP_C) |
ansond | 0:137634ff4186 | 41 | #include "polarssl/ecp.h" |
ansond | 0:137634ff4186 | 42 | #endif |
ansond | 0:137634ff4186 | 43 | #if defined(POLARSSL_ECDSA_C) |
ansond | 0:137634ff4186 | 44 | #include "polarssl/ecdsa.h" |
ansond | 0:137634ff4186 | 45 | #endif |
ansond | 0:137634ff4186 | 46 | #if defined(POLARSSL_PEM_WRITE_C) |
ansond | 0:137634ff4186 | 47 | #include "polarssl/pem.h" |
ansond | 0:137634ff4186 | 48 | #endif |
ansond | 0:137634ff4186 | 49 | |
ansond | 0:137634ff4186 | 50 | #if defined(POLARSSL_PLATFORM_C) |
ansond | 0:137634ff4186 | 51 | #include "polarssl/platform.h" |
ansond | 0:137634ff4186 | 52 | #else |
ansond | 0:137634ff4186 | 53 | #include <stdlib.h> |
ansond | 0:137634ff4186 | 54 | #define polarssl_malloc malloc |
ansond | 0:137634ff4186 | 55 | #define polarssl_free free |
ansond | 0:137634ff4186 | 56 | #endif |
ansond | 0:137634ff4186 | 57 | |
ansond | 0:137634ff4186 | 58 | #if defined(POLARSSL_RSA_C) |
ansond | 0:137634ff4186 | 59 | /* |
ansond | 0:137634ff4186 | 60 | * RSAPublicKey ::= SEQUENCE { |
ansond | 0:137634ff4186 | 61 | * modulus INTEGER, -- n |
ansond | 0:137634ff4186 | 62 | * publicExponent INTEGER -- e |
ansond | 0:137634ff4186 | 63 | * } |
ansond | 0:137634ff4186 | 64 | */ |
ansond | 0:137634ff4186 | 65 | static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, |
ansond | 0:137634ff4186 | 66 | rsa_context *rsa ) |
ansond | 0:137634ff4186 | 67 | { |
ansond | 0:137634ff4186 | 68 | int ret; |
ansond | 0:137634ff4186 | 69 | size_t len = 0; |
ansond | 0:137634ff4186 | 70 | |
ansond | 0:137634ff4186 | 71 | ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) ); |
ansond | 0:137634ff4186 | 72 | ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) ); |
ansond | 0:137634ff4186 | 73 | |
ansond | 0:137634ff4186 | 74 | ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); |
ansond | 0:137634ff4186 | 75 | ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | |
ansond | 0:137634ff4186 | 76 | ASN1_SEQUENCE ) ); |
ansond | 0:137634ff4186 | 77 | |
ansond | 0:137634ff4186 | 78 | return( (int) len ); |
ansond | 0:137634ff4186 | 79 | } |
ansond | 0:137634ff4186 | 80 | #endif /* POLARSSL_RSA_C */ |
ansond | 0:137634ff4186 | 81 | |
ansond | 0:137634ff4186 | 82 | #if defined(POLARSSL_ECP_C) |
ansond | 0:137634ff4186 | 83 | /* |
ansond | 0:137634ff4186 | 84 | * EC public key is an EC point |
ansond | 0:137634ff4186 | 85 | */ |
ansond | 0:137634ff4186 | 86 | static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, |
ansond | 0:137634ff4186 | 87 | ecp_keypair *ec ) |
ansond | 0:137634ff4186 | 88 | { |
ansond | 0:137634ff4186 | 89 | int ret; |
ansond | 0:137634ff4186 | 90 | size_t len = 0; |
ansond | 0:137634ff4186 | 91 | unsigned char buf[POLARSSL_ECP_MAX_PT_LEN]; |
ansond | 0:137634ff4186 | 92 | |
ansond | 0:137634ff4186 | 93 | if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q, |
ansond | 0:137634ff4186 | 94 | POLARSSL_ECP_PF_UNCOMPRESSED, |
ansond | 0:137634ff4186 | 95 | &len, buf, sizeof( buf ) ) ) != 0 ) |
ansond | 0:137634ff4186 | 96 | { |
ansond | 0:137634ff4186 | 97 | return( ret ); |
ansond | 0:137634ff4186 | 98 | } |
ansond | 0:137634ff4186 | 99 | |
ansond | 0:137634ff4186 | 100 | if( *p - start < (int) len ) |
ansond | 0:137634ff4186 | 101 | return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); |
ansond | 0:137634ff4186 | 102 | |
ansond | 0:137634ff4186 | 103 | *p -= len; |
ansond | 0:137634ff4186 | 104 | memcpy( *p, buf, len ); |
ansond | 0:137634ff4186 | 105 | |
ansond | 0:137634ff4186 | 106 | return( (int) len ); |
ansond | 0:137634ff4186 | 107 | } |
ansond | 0:137634ff4186 | 108 | |
ansond | 0:137634ff4186 | 109 | /* |
ansond | 0:137634ff4186 | 110 | * ECParameters ::= CHOICE { |
ansond | 0:137634ff4186 | 111 | * namedCurve OBJECT IDENTIFIER |
ansond | 0:137634ff4186 | 112 | * } |
ansond | 0:137634ff4186 | 113 | */ |
ansond | 0:137634ff4186 | 114 | static int pk_write_ec_param( unsigned char **p, unsigned char *start, |
ansond | 0:137634ff4186 | 115 | ecp_keypair *ec ) |
ansond | 0:137634ff4186 | 116 | { |
ansond | 0:137634ff4186 | 117 | int ret; |
ansond | 0:137634ff4186 | 118 | size_t len = 0; |
ansond | 0:137634ff4186 | 119 | const char *oid; |
ansond | 0:137634ff4186 | 120 | size_t oid_len; |
ansond | 0:137634ff4186 | 121 | |
ansond | 0:137634ff4186 | 122 | if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) |
ansond | 0:137634ff4186 | 123 | return( ret ); |
ansond | 0:137634ff4186 | 124 | |
ansond | 0:137634ff4186 | 125 | ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); |
ansond | 0:137634ff4186 | 126 | |
ansond | 0:137634ff4186 | 127 | return( (int) len ); |
ansond | 0:137634ff4186 | 128 | } |
ansond | 0:137634ff4186 | 129 | #endif /* POLARSSL_ECP_C */ |
ansond | 0:137634ff4186 | 130 | |
ansond | 0:137634ff4186 | 131 | int pk_write_pubkey( unsigned char **p, unsigned char *start, |
ansond | 0:137634ff4186 | 132 | const pk_context *key ) |
ansond | 0:137634ff4186 | 133 | { |
ansond | 0:137634ff4186 | 134 | int ret; |
ansond | 0:137634ff4186 | 135 | size_t len = 0; |
ansond | 0:137634ff4186 | 136 | |
ansond | 0:137634ff4186 | 137 | #if defined(POLARSSL_RSA_C) |
ansond | 0:137634ff4186 | 138 | if( pk_get_type( key ) == POLARSSL_PK_RSA ) |
ansond | 0:137634ff4186 | 139 | ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, pk_rsa( *key ) ) ); |
ansond | 0:137634ff4186 | 140 | else |
ansond | 0:137634ff4186 | 141 | #endif |
ansond | 0:137634ff4186 | 142 | #if defined(POLARSSL_ECP_C) |
ansond | 0:137634ff4186 | 143 | if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) |
ansond | 0:137634ff4186 | 144 | ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, pk_ec( *key ) ) ); |
ansond | 0:137634ff4186 | 145 | else |
ansond | 0:137634ff4186 | 146 | #endif |
ansond | 0:137634ff4186 | 147 | return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); |
ansond | 0:137634ff4186 | 148 | |
ansond | 0:137634ff4186 | 149 | return( (int) len ); |
ansond | 0:137634ff4186 | 150 | } |
ansond | 0:137634ff4186 | 151 | |
ansond | 0:137634ff4186 | 152 | int pk_write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) |
ansond | 0:137634ff4186 | 153 | { |
ansond | 0:137634ff4186 | 154 | int ret; |
ansond | 0:137634ff4186 | 155 | unsigned char *c; |
ansond | 0:137634ff4186 | 156 | size_t len = 0, par_len = 0, oid_len; |
ansond | 0:137634ff4186 | 157 | const char *oid; |
ansond | 0:137634ff4186 | 158 | |
ansond | 0:137634ff4186 | 159 | c = buf + size; |
ansond | 0:137634ff4186 | 160 | |
ansond | 0:137634ff4186 | 161 | ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, key ) ); |
ansond | 0:137634ff4186 | 162 | |
ansond | 0:137634ff4186 | 163 | if( c - buf < 1 ) |
ansond | 0:137634ff4186 | 164 | return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); |
ansond | 0:137634ff4186 | 165 | |
ansond | 0:137634ff4186 | 166 | /* |
ansond | 0:137634ff4186 | 167 | * SubjectPublicKeyInfo ::= SEQUENCE { |
ansond | 0:137634ff4186 | 168 | * algorithm AlgorithmIdentifier, |
ansond | 0:137634ff4186 | 169 | * subjectPublicKey BIT STRING } |
ansond | 0:137634ff4186 | 170 | */ |
ansond | 0:137634ff4186 | 171 | *--c = 0; |
ansond | 0:137634ff4186 | 172 | len += 1; |
ansond | 0:137634ff4186 | 173 | |
ansond | 0:137634ff4186 | 174 | ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); |
ansond | 0:137634ff4186 | 175 | ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); |
ansond | 0:137634ff4186 | 176 | |
ansond | 0:137634ff4186 | 177 | if( ( ret = oid_get_oid_by_pk_alg( pk_get_type( key ), |
ansond | 0:137634ff4186 | 178 | &oid, &oid_len ) ) != 0 ) |
ansond | 0:137634ff4186 | 179 | { |
ansond | 0:137634ff4186 | 180 | return( ret ); |
ansond | 0:137634ff4186 | 181 | } |
ansond | 0:137634ff4186 | 182 | |
ansond | 0:137634ff4186 | 183 | #if defined(POLARSSL_ECP_C) |
ansond | 0:137634ff4186 | 184 | if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) |
ansond | 0:137634ff4186 | 185 | { |
ansond | 0:137634ff4186 | 186 | ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, pk_ec( *key ) ) ); |
ansond | 0:137634ff4186 | 187 | } |
ansond | 0:137634ff4186 | 188 | #endif |
ansond | 0:137634ff4186 | 189 | |
ansond | 0:137634ff4186 | 190 | ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, oid, oid_len, |
ansond | 0:137634ff4186 | 191 | par_len ) ); |
ansond | 0:137634ff4186 | 192 | |
ansond | 0:137634ff4186 | 193 | ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); |
ansond | 0:137634ff4186 | 194 | ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | |
ansond | 0:137634ff4186 | 195 | ASN1_SEQUENCE ) ); |
ansond | 0:137634ff4186 | 196 | |
ansond | 0:137634ff4186 | 197 | return( (int) len ); |
ansond | 0:137634ff4186 | 198 | } |
ansond | 0:137634ff4186 | 199 | |
ansond | 0:137634ff4186 | 200 | int pk_write_key_der( pk_context *key, unsigned char *buf, size_t size ) |
ansond | 0:137634ff4186 | 201 | { |
ansond | 0:137634ff4186 | 202 | int ret; |
ansond | 0:137634ff4186 | 203 | unsigned char *c = buf + size; |
ansond | 0:137634ff4186 | 204 | size_t len = 0; |
ansond | 0:137634ff4186 | 205 | |
ansond | 0:137634ff4186 | 206 | #if defined(POLARSSL_RSA_C) |
ansond | 0:137634ff4186 | 207 | if( pk_get_type( key ) == POLARSSL_PK_RSA ) |
ansond | 0:137634ff4186 | 208 | { |
ansond | 0:137634ff4186 | 209 | rsa_context *rsa = pk_rsa( *key ); |
ansond | 0:137634ff4186 | 210 | |
ansond | 0:137634ff4186 | 211 | ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) ); |
ansond | 0:137634ff4186 | 212 | ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) ); |
ansond | 0:137634ff4186 | 213 | ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) ); |
ansond | 0:137634ff4186 | 214 | ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) ); |
ansond | 0:137634ff4186 | 215 | ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) ); |
ansond | 0:137634ff4186 | 216 | ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) ); |
ansond | 0:137634ff4186 | 217 | ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) ); |
ansond | 0:137634ff4186 | 218 | ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) ); |
ansond | 0:137634ff4186 | 219 | ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) ); |
ansond | 0:137634ff4186 | 220 | |
ansond | 0:137634ff4186 | 221 | ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); |
ansond | 0:137634ff4186 | 222 | ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | |
ansond | 0:137634ff4186 | 223 | ASN1_SEQUENCE ) ); |
ansond | 0:137634ff4186 | 224 | } |
ansond | 0:137634ff4186 | 225 | else |
ansond | 0:137634ff4186 | 226 | #endif /* POLARSSL_RSA_C */ |
ansond | 0:137634ff4186 | 227 | #if defined(POLARSSL_ECP_C) |
ansond | 0:137634ff4186 | 228 | if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) |
ansond | 0:137634ff4186 | 229 | { |
ansond | 0:137634ff4186 | 230 | ecp_keypair *ec = pk_ec( *key ); |
ansond | 0:137634ff4186 | 231 | size_t pub_len = 0, par_len = 0; |
ansond | 0:137634ff4186 | 232 | |
ansond | 0:137634ff4186 | 233 | /* |
ansond | 0:137634ff4186 | 234 | * RFC 5915, or SEC1 Appendix C.4 |
ansond | 0:137634ff4186 | 235 | * |
ansond | 0:137634ff4186 | 236 | * ECPrivateKey ::= SEQUENCE { |
ansond | 0:137634ff4186 | 237 | * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), |
ansond | 0:137634ff4186 | 238 | * privateKey OCTET STRING, |
ansond | 0:137634ff4186 | 239 | * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, |
ansond | 0:137634ff4186 | 240 | * publicKey [1] BIT STRING OPTIONAL |
ansond | 0:137634ff4186 | 241 | * } |
ansond | 0:137634ff4186 | 242 | */ |
ansond | 0:137634ff4186 | 243 | |
ansond | 0:137634ff4186 | 244 | /* publicKey */ |
ansond | 0:137634ff4186 | 245 | ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); |
ansond | 0:137634ff4186 | 246 | |
ansond | 0:137634ff4186 | 247 | if( c - buf < 1 ) |
ansond | 0:137634ff4186 | 248 | return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); |
ansond | 0:137634ff4186 | 249 | *--c = 0; |
ansond | 0:137634ff4186 | 250 | pub_len += 1; |
ansond | 0:137634ff4186 | 251 | |
ansond | 0:137634ff4186 | 252 | ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) ); |
ansond | 0:137634ff4186 | 253 | ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); |
ansond | 0:137634ff4186 | 254 | |
ansond | 0:137634ff4186 | 255 | ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) ); |
ansond | 0:137634ff4186 | 256 | ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, |
ansond | 0:137634ff4186 | 257 | ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ); |
ansond | 0:137634ff4186 | 258 | len += pub_len; |
ansond | 0:137634ff4186 | 259 | |
ansond | 0:137634ff4186 | 260 | /* parameters */ |
ansond | 0:137634ff4186 | 261 | ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); |
ansond | 0:137634ff4186 | 262 | |
ansond | 0:137634ff4186 | 263 | ASN1_CHK_ADD( par_len, asn1_write_len( &c, buf, par_len ) ); |
ansond | 0:137634ff4186 | 264 | ASN1_CHK_ADD( par_len, asn1_write_tag( &c, buf, |
ansond | 0:137634ff4186 | 265 | ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ); |
ansond | 0:137634ff4186 | 266 | len += par_len; |
ansond | 0:137634ff4186 | 267 | |
ansond | 0:137634ff4186 | 268 | /* privateKey: write as MPI then fix tag */ |
ansond | 0:137634ff4186 | 269 | ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &ec->d ) ); |
ansond | 0:137634ff4186 | 270 | *c = ASN1_OCTET_STRING; |
ansond | 0:137634ff4186 | 271 | |
ansond | 0:137634ff4186 | 272 | /* version */ |
ansond | 0:137634ff4186 | 273 | ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) ); |
ansond | 0:137634ff4186 | 274 | |
ansond | 0:137634ff4186 | 275 | ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); |
ansond | 0:137634ff4186 | 276 | ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | |
ansond | 0:137634ff4186 | 277 | ASN1_SEQUENCE ) ); |
ansond | 0:137634ff4186 | 278 | } |
ansond | 0:137634ff4186 | 279 | else |
ansond | 0:137634ff4186 | 280 | #endif /* POLARSSL_ECP_C */ |
ansond | 0:137634ff4186 | 281 | return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); |
ansond | 0:137634ff4186 | 282 | |
ansond | 0:137634ff4186 | 283 | return( (int) len ); |
ansond | 0:137634ff4186 | 284 | } |
ansond | 0:137634ff4186 | 285 | |
ansond | 0:137634ff4186 | 286 | #if defined(POLARSSL_PEM_WRITE_C) |
ansond | 0:137634ff4186 | 287 | |
ansond | 0:137634ff4186 | 288 | #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" |
ansond | 0:137634ff4186 | 289 | #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" |
ansond | 0:137634ff4186 | 290 | |
ansond | 0:137634ff4186 | 291 | #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" |
ansond | 0:137634ff4186 | 292 | #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" |
ansond | 0:137634ff4186 | 293 | #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" |
ansond | 0:137634ff4186 | 294 | #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" |
ansond | 0:137634ff4186 | 295 | |
ansond | 0:137634ff4186 | 296 | /* |
ansond | 0:137634ff4186 | 297 | * Max sizes of key per types. Shown as tag + len (+ content). |
ansond | 0:137634ff4186 | 298 | */ |
ansond | 0:137634ff4186 | 299 | |
ansond | 0:137634ff4186 | 300 | #if defined(POLARSSL_RSA_C) |
ansond | 0:137634ff4186 | 301 | /* |
ansond | 0:137634ff4186 | 302 | * RSA public keys: |
ansond | 0:137634ff4186 | 303 | * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 |
ansond | 0:137634ff4186 | 304 | * algorithm AlgorithmIdentifier, 1 + 1 (sequence) |
ansond | 0:137634ff4186 | 305 | * + 1 + 1 + 9 (rsa oid) |
ansond | 0:137634ff4186 | 306 | * + 1 + 1 (params null) |
ansond | 0:137634ff4186 | 307 | * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) |
ansond | 0:137634ff4186 | 308 | * RSAPublicKey ::= SEQUENCE { 1 + 3 |
ansond | 0:137634ff4186 | 309 | * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 |
ansond | 0:137634ff4186 | 310 | * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 |
ansond | 0:137634ff4186 | 311 | * } |
ansond | 0:137634ff4186 | 312 | */ |
ansond | 0:137634ff4186 | 313 | #define RSA_PUB_DER_MAX_BYTES 38 + 2 * POLARSSL_MPI_MAX_SIZE |
ansond | 0:137634ff4186 | 314 | |
ansond | 0:137634ff4186 | 315 | /* |
ansond | 0:137634ff4186 | 316 | * RSA private keys: |
ansond | 0:137634ff4186 | 317 | * RSAPrivateKey ::= SEQUENCE { 1 + 3 |
ansond | 0:137634ff4186 | 318 | * version Version, 1 + 1 + 1 |
ansond | 0:137634ff4186 | 319 | * modulus INTEGER, 1 + 3 + MPI_MAX + 1 |
ansond | 0:137634ff4186 | 320 | * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 |
ansond | 0:137634ff4186 | 321 | * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 |
ansond | 0:137634ff4186 | 322 | * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
ansond | 0:137634ff4186 | 323 | * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
ansond | 0:137634ff4186 | 324 | * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
ansond | 0:137634ff4186 | 325 | * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
ansond | 0:137634ff4186 | 326 | * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
ansond | 0:137634ff4186 | 327 | * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) |
ansond | 0:137634ff4186 | 328 | * } |
ansond | 0:137634ff4186 | 329 | */ |
ansond | 0:137634ff4186 | 330 | #define MPI_MAX_SIZE_2 POLARSSL_MPI_MAX_SIZE / 2 + \ |
ansond | 0:137634ff4186 | 331 | POLARSSL_MPI_MAX_SIZE % 2 |
ansond | 0:137634ff4186 | 332 | #define RSA_PRV_DER_MAX_BYTES 47 + 3 * POLARSSL_MPI_MAX_SIZE \ |
ansond | 0:137634ff4186 | 333 | + 5 * MPI_MAX_SIZE_2 |
ansond | 0:137634ff4186 | 334 | |
ansond | 0:137634ff4186 | 335 | #else /* POLARSSL_RSA_C */ |
ansond | 0:137634ff4186 | 336 | |
ansond | 0:137634ff4186 | 337 | #define RSA_PUB_DER_MAX_BYTES 0 |
ansond | 0:137634ff4186 | 338 | #define RSA_PRV_DER_MAX_BYTES 0 |
ansond | 0:137634ff4186 | 339 | |
ansond | 0:137634ff4186 | 340 | #endif /* POLARSSL_RSA_C */ |
ansond | 0:137634ff4186 | 341 | |
ansond | 0:137634ff4186 | 342 | #if defined(POLARSSL_ECP_C) |
ansond | 0:137634ff4186 | 343 | /* |
ansond | 0:137634ff4186 | 344 | * EC public keys: |
ansond | 0:137634ff4186 | 345 | * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 |
ansond | 0:137634ff4186 | 346 | * algorithm AlgorithmIdentifier, 1 + 1 (sequence) |
ansond | 0:137634ff4186 | 347 | * + 1 + 1 + 7 (ec oid) |
ansond | 0:137634ff4186 | 348 | * + 1 + 1 + 9 (namedCurve oid) |
ansond | 0:137634ff4186 | 349 | * subjectPublicKey BIT STRING 1 + 2 + 1 [1] |
ansond | 0:137634ff4186 | 350 | * + 1 (point format) [1] |
ansond | 0:137634ff4186 | 351 | * + 2 * ECP_MAX (coords) [1] |
ansond | 0:137634ff4186 | 352 | * } |
ansond | 0:137634ff4186 | 353 | */ |
ansond | 0:137634ff4186 | 354 | #define ECP_PUB_DER_MAX_BYTES 30 + 2 * POLARSSL_ECP_MAX_BYTES |
ansond | 0:137634ff4186 | 355 | |
ansond | 0:137634ff4186 | 356 | /* |
ansond | 0:137634ff4186 | 357 | * EC private keys: |
ansond | 0:137634ff4186 | 358 | * ECPrivateKey ::= SEQUENCE { 1 + 2 |
ansond | 0:137634ff4186 | 359 | * version INTEGER , 1 + 1 + 1 |
ansond | 0:137634ff4186 | 360 | * privateKey OCTET STRING, 1 + 1 + ECP_MAX |
ansond | 0:137634ff4186 | 361 | * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) |
ansond | 0:137634ff4186 | 362 | * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above |
ansond | 0:137634ff4186 | 363 | * } |
ansond | 0:137634ff4186 | 364 | */ |
ansond | 0:137634ff4186 | 365 | #define ECP_PRV_DER_MAX_BYTES 29 + 3 * POLARSSL_ECP_MAX_BYTES |
ansond | 0:137634ff4186 | 366 | |
ansond | 0:137634ff4186 | 367 | #else /* POLARSSL_ECP_C */ |
ansond | 0:137634ff4186 | 368 | |
ansond | 0:137634ff4186 | 369 | #define ECP_PUB_DER_MAX_BYTES 0 |
ansond | 0:137634ff4186 | 370 | #define ECP_PRV_DER_MAX_BYTES 0 |
ansond | 0:137634ff4186 | 371 | |
ansond | 0:137634ff4186 | 372 | #endif /* POLARSSL_ECP_C */ |
ansond | 0:137634ff4186 | 373 | |
ansond | 0:137634ff4186 | 374 | #define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ |
ansond | 0:137634ff4186 | 375 | RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES |
ansond | 0:137634ff4186 | 376 | #define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ |
ansond | 0:137634ff4186 | 377 | RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES |
ansond | 0:137634ff4186 | 378 | |
ansond | 0:137634ff4186 | 379 | int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size ) |
ansond | 0:137634ff4186 | 380 | { |
ansond | 0:137634ff4186 | 381 | int ret; |
ansond | 0:137634ff4186 | 382 | unsigned char output_buf[PUB_DER_MAX_BYTES]; |
ansond | 0:137634ff4186 | 383 | size_t olen = 0; |
ansond | 0:137634ff4186 | 384 | |
ansond | 0:137634ff4186 | 385 | if( ( ret = pk_write_pubkey_der( key, output_buf, |
ansond | 0:137634ff4186 | 386 | sizeof(output_buf) ) ) < 0 ) |
ansond | 0:137634ff4186 | 387 | { |
ansond | 0:137634ff4186 | 388 | return( ret ); |
ansond | 0:137634ff4186 | 389 | } |
ansond | 0:137634ff4186 | 390 | |
ansond | 0:137634ff4186 | 391 | if( ( ret = pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, |
ansond | 0:137634ff4186 | 392 | output_buf + sizeof(output_buf) - ret, |
ansond | 0:137634ff4186 | 393 | ret, buf, size, &olen ) ) != 0 ) |
ansond | 0:137634ff4186 | 394 | { |
ansond | 0:137634ff4186 | 395 | return( ret ); |
ansond | 0:137634ff4186 | 396 | } |
ansond | 0:137634ff4186 | 397 | |
ansond | 0:137634ff4186 | 398 | return( 0 ); |
ansond | 0:137634ff4186 | 399 | } |
ansond | 0:137634ff4186 | 400 | |
ansond | 0:137634ff4186 | 401 | int pk_write_key_pem( pk_context *key, unsigned char *buf, size_t size ) |
ansond | 0:137634ff4186 | 402 | { |
ansond | 0:137634ff4186 | 403 | int ret; |
ansond | 0:137634ff4186 | 404 | unsigned char output_buf[PRV_DER_MAX_BYTES]; |
ansond | 0:137634ff4186 | 405 | const char *begin, *end; |
ansond | 0:137634ff4186 | 406 | size_t olen = 0; |
ansond | 0:137634ff4186 | 407 | |
ansond | 0:137634ff4186 | 408 | if( ( ret = pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) |
ansond | 0:137634ff4186 | 409 | return( ret ); |
ansond | 0:137634ff4186 | 410 | |
ansond | 0:137634ff4186 | 411 | #if defined(POLARSSL_RSA_C) |
ansond | 0:137634ff4186 | 412 | if( pk_get_type( key ) == POLARSSL_PK_RSA ) |
ansond | 0:137634ff4186 | 413 | { |
ansond | 0:137634ff4186 | 414 | begin = PEM_BEGIN_PRIVATE_KEY_RSA; |
ansond | 0:137634ff4186 | 415 | end = PEM_END_PRIVATE_KEY_RSA; |
ansond | 0:137634ff4186 | 416 | } |
ansond | 0:137634ff4186 | 417 | else |
ansond | 0:137634ff4186 | 418 | #endif |
ansond | 0:137634ff4186 | 419 | #if defined(POLARSSL_ECP_C) |
ansond | 0:137634ff4186 | 420 | if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) |
ansond | 0:137634ff4186 | 421 | { |
ansond | 0:137634ff4186 | 422 | begin = PEM_BEGIN_PRIVATE_KEY_EC; |
ansond | 0:137634ff4186 | 423 | end = PEM_END_PRIVATE_KEY_EC; |
ansond | 0:137634ff4186 | 424 | } |
ansond | 0:137634ff4186 | 425 | else |
ansond | 0:137634ff4186 | 426 | #endif |
ansond | 0:137634ff4186 | 427 | return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); |
ansond | 0:137634ff4186 | 428 | |
ansond | 0:137634ff4186 | 429 | if( ( ret = pem_write_buffer( begin, end, |
ansond | 0:137634ff4186 | 430 | output_buf + sizeof(output_buf) - ret, |
ansond | 0:137634ff4186 | 431 | ret, buf, size, &olen ) ) != 0 ) |
ansond | 0:137634ff4186 | 432 | { |
ansond | 0:137634ff4186 | 433 | return( ret ); |
ansond | 0:137634ff4186 | 434 | } |
ansond | 0:137634ff4186 | 435 | |
ansond | 0:137634ff4186 | 436 | return( 0 ); |
ansond | 0:137634ff4186 | 437 | } |
ansond | 0:137634ff4186 | 438 | #endif /* POLARSSL_PEM_WRITE_C */ |
ansond | 0:137634ff4186 | 439 | |
ansond | 0:137634ff4186 | 440 | #endif /* POLARSSL_PK_WRITE_C */ |
ansond | 0:137634ff4186 | 441 |