STM32F7 Ethernet interface for nucleo STM32F767

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pkwrite.c Source File

pkwrite.c

00001 /*
00002  *  Public Key layer for writing key files and structures
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 
00022 #if !defined(MBEDTLS_CONFIG_FILE)
00023 #include "mbedtls/config.h"
00024 #else
00025 #include MBEDTLS_CONFIG_FILE
00026 #endif
00027 
00028 #if defined(MBEDTLS_PK_WRITE_C)
00029 
00030 #include "mbedtls/pk.h"
00031 #include "mbedtls/asn1write.h"
00032 #include "mbedtls/oid.h"
00033 
00034 #include <string.h>
00035 
00036 #if defined(MBEDTLS_RSA_C)
00037 #include "mbedtls/rsa.h"
00038 #endif
00039 #if defined(MBEDTLS_ECP_C)
00040 #include "mbedtls/ecp.h"
00041 #endif
00042 #if defined(MBEDTLS_ECDSA_C)
00043 #include "mbedtls/ecdsa.h"
00044 #endif
00045 #if defined(MBEDTLS_PEM_WRITE_C)
00046 #include "mbedtls/pem.h"
00047 #endif
00048 
00049 #if defined(MBEDTLS_PLATFORM_C)
00050 #include "mbedtls/platform.h"
00051 #else
00052 #include <stdlib.h>
00053 #define mbedtls_calloc    calloc
00054 #define mbedtls_free       free
00055 #endif
00056 
00057 #if defined(MBEDTLS_RSA_C)
00058 /*
00059  *  RSAPublicKey ::= SEQUENCE {
00060  *      modulus           INTEGER,  -- n
00061  *      publicExponent    INTEGER   -- e
00062  *  }
00063  */
00064 static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
00065                                   mbedtls_rsa_context *rsa )
00066 {
00067     int ret;
00068     size_t len = 0;
00069 
00070     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->E  ) );
00071     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->N  ) );
00072 
00073     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00074     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
00075                                                  MBEDTLS_ASN1_SEQUENCE ) );
00076 
00077     return( (int) len );
00078 }
00079 #endif /* MBEDTLS_RSA_C */
00080 
00081 #if defined(MBEDTLS_ECP_C)
00082 /*
00083  * EC public key is an EC point
00084  */
00085 static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
00086                                  mbedtls_ecp_keypair *ec )
00087 {
00088     int ret;
00089     size_t len = 0;
00090     unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
00091 
00092     if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp , &ec->Q ,
00093                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
00094                                         &len, buf, sizeof( buf ) ) ) != 0 )
00095     {
00096         return( ret );
00097     }
00098 
00099     if( *p < start || (size_t)( *p - start ) < len )
00100         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00101 
00102     *p -= len;
00103     memcpy( *p, buf, len );
00104 
00105     return( (int) len );
00106 }
00107 
00108 /*
00109  * ECParameters ::= CHOICE {
00110  *   namedCurve         OBJECT IDENTIFIER
00111  * }
00112  */
00113 static int pk_write_ec_param( unsigned char **p, unsigned char *start,
00114                                 mbedtls_ecp_keypair *ec )
00115 {
00116     int ret;
00117     size_t len = 0;
00118     const char *oid;
00119     size_t oid_len;
00120 
00121     if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp .id , &oid, &oid_len ) ) != 0 )
00122         return( ret );
00123 
00124     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
00125 
00126     return( (int) len );
00127 }
00128 #endif /* MBEDTLS_ECP_C */
00129 
00130 int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
00131                      const mbedtls_pk_context *key )
00132 {
00133     int ret;
00134     size_t len = 0;
00135 
00136 #if defined(MBEDTLS_RSA_C)
00137     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
00138         MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) );
00139     else
00140 #endif
00141 #if defined(MBEDTLS_ECP_C)
00142     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
00143         MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) );
00144     else
00145 #endif
00146         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
00147 
00148     return( (int) len );
00149 }
00150 
00151 int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
00152 {
00153     int ret;
00154     unsigned char *c;
00155     size_t len = 0, par_len = 0, oid_len;
00156     const char *oid;
00157 
00158     c = buf + size;
00159 
00160     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
00161 
00162     if( c - buf < 1 )
00163         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00164 
00165     /*
00166      *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
00167      *       algorithm            AlgorithmIdentifier,
00168      *       subjectPublicKey     BIT STRING }
00169      */
00170     *--c = 0;
00171     len += 1;
00172 
00173     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00174     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
00175 
00176     if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ),
00177                                        &oid, &oid_len ) ) != 0 )
00178     {
00179         return( ret );
00180     }
00181 
00182 #if defined(MBEDTLS_ECP_C)
00183     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
00184     {
00185         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) );
00186     }
00187 #endif
00188 
00189     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
00190                                                         par_len ) );
00191 
00192     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00193     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
00194                                                 MBEDTLS_ASN1_SEQUENCE ) );
00195 
00196     return( (int) len );
00197 }
00198 
00199 int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
00200 {
00201     int ret;
00202     unsigned char *c = buf + size;
00203     size_t len = 0;
00204 
00205 #if defined(MBEDTLS_RSA_C)
00206     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
00207     {
00208         mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key );
00209 
00210         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->QP  ) );
00211         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DQ  ) );
00212         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DP  ) );
00213         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->Q  ) );
00214         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->P  ) );
00215         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->D  ) );
00216         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->E  ) );
00217         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->N  ) );
00218         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
00219 
00220         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00221         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
00222                                                     MBEDTLS_ASN1_SEQUENCE ) );
00223     }
00224     else
00225 #endif /* MBEDTLS_RSA_C */
00226 #if defined(MBEDTLS_ECP_C)
00227     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
00228     {
00229         mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key );
00230         size_t pub_len = 0, par_len = 0;
00231 
00232         /*
00233          * RFC 5915, or SEC1 Appendix C.4
00234          *
00235          * ECPrivateKey ::= SEQUENCE {
00236          *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
00237          *      privateKey     OCTET STRING,
00238          *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
00239          *      publicKey  [1] BIT STRING OPTIONAL
00240          *    }
00241          */
00242 
00243         /* publicKey */
00244         MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
00245 
00246         if( c - buf < 1 )
00247             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00248         *--c = 0;
00249         pub_len += 1;
00250 
00251         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
00252         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
00253 
00254         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
00255         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf,
00256                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) );
00257         len += pub_len;
00258 
00259         /* parameters */
00260         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
00261 
00262         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) );
00263         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf,
00264                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
00265         len += par_len;
00266 
00267         /* privateKey: write as MPI then fix tag */
00268         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d  ) );
00269         *c = MBEDTLS_ASN1_OCTET_STRING;
00270 
00271         /* version */
00272         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );
00273 
00274         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00275         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
00276                                                     MBEDTLS_ASN1_SEQUENCE ) );
00277     }
00278     else
00279 #endif /* MBEDTLS_ECP_C */
00280         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
00281 
00282     return( (int) len );
00283 }
00284 
00285 #if defined(MBEDTLS_PEM_WRITE_C)
00286 
00287 #define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"
00288 #define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"
00289 
00290 #define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"
00291 #define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"
00292 #define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
00293 #define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"
00294 
00295 /*
00296  * Max sizes of key per types. Shown as tag + len (+ content).
00297  */
00298 
00299 #if defined(MBEDTLS_RSA_C)
00300 /*
00301  * RSA public keys:
00302  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
00303  *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
00304  *                                                + 1 + 1 + 9 (rsa oid)
00305  *                                                + 1 + 1 (params null)
00306  *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
00307  *  RSAPublicKey ::= SEQUENCE {                     1 + 3
00308  *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
00309  *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
00310  *  }
00311  */
00312 #define RSA_PUB_DER_MAX_BYTES   38 + 2 * MBEDTLS_MPI_MAX_SIZE
00313 
00314 /*
00315  * RSA private keys:
00316  *  RSAPrivateKey ::= SEQUENCE {                    1 + 3
00317  *      version           Version,                  1 + 1 + 1
00318  *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1
00319  *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1
00320  *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1
00321  *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00322  *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00323  *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00324  *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00325  *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00326  *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
00327  *  }
00328  */
00329 #define MPI_MAX_SIZE_2          MBEDTLS_MPI_MAX_SIZE / 2 + \
00330                                 MBEDTLS_MPI_MAX_SIZE % 2
00331 #define RSA_PRV_DER_MAX_BYTES   47 + 3 * MBEDTLS_MPI_MAX_SIZE \
00332                                    + 5 * MPI_MAX_SIZE_2
00333 
00334 #else /* MBEDTLS_RSA_C */
00335 
00336 #define RSA_PUB_DER_MAX_BYTES   0
00337 #define RSA_PRV_DER_MAX_BYTES   0
00338 
00339 #endif /* MBEDTLS_RSA_C */
00340 
00341 #if defined(MBEDTLS_ECP_C)
00342 /*
00343  * EC public keys:
00344  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2
00345  *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)
00346  *                                            + 1 + 1 + 7 (ec oid)
00347  *                                            + 1 + 1 + 9 (namedCurve oid)
00348  *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]
00349  *                                            + 1 (point format)        [1]
00350  *                                            + 2 * ECP_MAX (coords)    [1]
00351  *  }
00352  */
00353 #define ECP_PUB_DER_MAX_BYTES   30 + 2 * MBEDTLS_ECP_MAX_BYTES
00354 
00355 /*
00356  * EC private keys:
00357  * ECPrivateKey ::= SEQUENCE {                  1 + 2
00358  *      version        INTEGER ,                1 + 1 + 1
00359  *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX
00360  *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)
00361  *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
00362  *    }
00363  */
00364 #define ECP_PRV_DER_MAX_BYTES   29 + 3 * MBEDTLS_ECP_MAX_BYTES
00365 
00366 #else /* MBEDTLS_ECP_C */
00367 
00368 #define ECP_PUB_DER_MAX_BYTES   0
00369 #define ECP_PRV_DER_MAX_BYTES   0
00370 
00371 #endif /* MBEDTLS_ECP_C */
00372 
00373 #define PUB_DER_MAX_BYTES   RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
00374                             RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
00375 #define PRV_DER_MAX_BYTES   RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
00376                             RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
00377 
00378 int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
00379 {
00380     int ret;
00381     unsigned char output_buf[PUB_DER_MAX_BYTES];
00382     size_t olen = 0;
00383 
00384     if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf,
00385                                      sizeof(output_buf) ) ) < 0 )
00386     {
00387         return( ret );
00388     }
00389 
00390     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
00391                                   output_buf + sizeof(output_buf) - ret,
00392                                   ret, buf, size, &olen ) ) != 0 )
00393     {
00394         return( ret );
00395     }
00396 
00397     return( 0 );
00398 }
00399 
00400 int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
00401 {
00402     int ret;
00403     unsigned char output_buf[PRV_DER_MAX_BYTES];
00404     const char *begin, *end;
00405     size_t olen = 0;
00406 
00407     if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
00408         return( ret );
00409 
00410 #if defined(MBEDTLS_RSA_C)
00411     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
00412     {
00413         begin = PEM_BEGIN_PRIVATE_KEY_RSA;
00414         end = PEM_END_PRIVATE_KEY_RSA;
00415     }
00416     else
00417 #endif
00418 #if defined(MBEDTLS_ECP_C)
00419     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
00420     {
00421         begin = PEM_BEGIN_PRIVATE_KEY_EC;
00422         end = PEM_END_PRIVATE_KEY_EC;
00423     }
00424     else
00425 #endif
00426         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
00427 
00428     if( ( ret = mbedtls_pem_write_buffer( begin, end,
00429                                   output_buf + sizeof(output_buf) - ret,
00430                                   ret, buf, size, &olen ) ) != 0 )
00431     {
00432         return( ret );
00433     }
00434 
00435     return( 0 );
00436 }
00437 #endif /* MBEDTLS_PEM_WRITE_C */
00438 
00439 #endif /* MBEDTLS_PK_WRITE_C */