Example program to test AES-GCM functionality. Used for a workshop

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pem.c Source File

pem.c

00001 /*
00002  *  Privacy Enhanced Mail (PEM) decoding
00003  *
00004  *  Copyright (C) 2006-2014, Brainspark B.V.
00005  *
00006  *  This file is part of PolarSSL (http://www.polarssl.org)
00007  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
00008  *
00009  *  All rights reserved.
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License along
00022  *  with this program; if not, write to the Free Software Foundation, Inc.,
00023  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00024  */
00025 
00026 #if !defined(POLARSSL_CONFIG_FILE)
00027 #include "polarssl/config.h"
00028 #else
00029 #include POLARSSL_CONFIG_FILE
00030 #endif
00031 
00032 #if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C)
00033 #include "polarssl/pem.h"
00034 #include "polarssl/base64.h"
00035 #include "polarssl/des.h"
00036 #include "polarssl/aes.h"
00037 #include "polarssl/md5.h"
00038 #include "polarssl/cipher.h"
00039 
00040 #if defined(POLARSSL_PLATFORM_C)
00041 #include "polarssl/platform.h"
00042 #else
00043 #define polarssl_malloc     malloc
00044 #define polarssl_free       free
00045 #endif
00046 
00047 #include <stdlib.h>
00048 
00049 #if defined(POLARSSL_PEM_PARSE_C)
00050 void pem_init( pem_context *ctx )
00051 {
00052     memset( ctx, 0, sizeof( pem_context ) );
00053 }
00054 
00055 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
00056     ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
00057 /*
00058  * Read a 16-byte hex string and convert it to binary
00059  */
00060 static int pem_get_iv( const unsigned char *s, unsigned char *iv,
00061                        size_t iv_len )
00062 {
00063     size_t i, j, k;
00064 
00065     memset( iv, 0, iv_len );
00066 
00067     for( i = 0; i < iv_len * 2; i++, s++ )
00068     {
00069         if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
00070         if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
00071         if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
00072             return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
00073 
00074         k = ( ( i & 1 ) != 0 ) ? j : j << 4;
00075 
00076         iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
00077     }
00078 
00079     return( 0 );
00080 }
00081 
00082 static void pem_pbkdf1( unsigned char *key, size_t keylen,
00083                         unsigned char *iv,
00084                         const unsigned char *pwd, size_t pwdlen )
00085 {
00086     md5_context md5_ctx;
00087     unsigned char md5sum[16];
00088     size_t use_len;
00089 
00090     /*
00091      * key[ 0..15] = MD5(pwd || IV)
00092      */
00093     md5_starts( &md5_ctx );
00094     md5_update( &md5_ctx, pwd, pwdlen );
00095     md5_update( &md5_ctx, iv,  8 );
00096     md5_finish( &md5_ctx, md5sum );
00097 
00098     if( keylen <= 16 )
00099     {
00100         memcpy( key, md5sum, keylen );
00101 
00102         memset( &md5_ctx, 0, sizeof(  md5_ctx ) );
00103         memset( md5sum, 0, 16 );
00104         return;
00105     }
00106 
00107     memcpy( key, md5sum, 16 );
00108 
00109     /*
00110      * key[16..23] = MD5(key[ 0..15] || pwd || IV])
00111      */
00112     md5_starts( &md5_ctx );
00113     md5_update( &md5_ctx, md5sum,  16 );
00114     md5_update( &md5_ctx, pwd, pwdlen );
00115     md5_update( &md5_ctx, iv,  8 );
00116     md5_finish( &md5_ctx, md5sum );
00117 
00118     use_len = 16;
00119     if( keylen < 32 )
00120         use_len = keylen - 16;
00121 
00122     memcpy( key + 16, md5sum, use_len );
00123 
00124     memset( &md5_ctx, 0, sizeof(  md5_ctx ) );
00125     memset( md5sum, 0, 16 );
00126 }
00127 
00128 #if defined(POLARSSL_DES_C)
00129 /*
00130  * Decrypt with DES-CBC, using PBKDF1 for key derivation
00131  */
00132 static void pem_des_decrypt( unsigned char des_iv[8],
00133                                unsigned char *buf, size_t buflen,
00134                                const unsigned char *pwd, size_t pwdlen )
00135 {
00136     des_context des_ctx;
00137     unsigned char des_key[8];
00138 
00139     pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
00140 
00141     des_setkey_dec( &des_ctx, des_key );
00142     des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen,
00143                      des_iv, buf, buf );
00144 
00145     memset( &des_ctx, 0, sizeof( des_ctx ) );
00146     memset( des_key, 0, 8 );
00147 }
00148 
00149 /*
00150  * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
00151  */
00152 static void pem_des3_decrypt( unsigned char des3_iv[8],
00153                                unsigned char *buf, size_t buflen,
00154                                const unsigned char *pwd, size_t pwdlen )
00155 {
00156     des3_context des3_ctx;
00157     unsigned char des3_key[24];
00158 
00159     pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
00160 
00161     des3_set3key_dec( &des3_ctx, des3_key );
00162     des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
00163                      des3_iv, buf, buf );
00164 
00165     memset( &des3_ctx, 0, sizeof( des3_ctx ) );
00166     memset( des3_key, 0, 24 );
00167 }
00168 #endif /* POLARSSL_DES_C */
00169 
00170 #if defined(POLARSSL_AES_C)
00171 /*
00172  * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
00173  */
00174 static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
00175                                unsigned char *buf, size_t buflen,
00176                                const unsigned char *pwd, size_t pwdlen )
00177 {
00178     aes_context aes_ctx;
00179     unsigned char aes_key[32];
00180 
00181     pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
00182 
00183     aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
00184     aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen,
00185                      aes_iv, buf, buf );
00186 
00187     memset( &aes_ctx, 0, sizeof( aes_ctx ) );
00188     memset( aes_key, 0, keylen );
00189 }
00190 #endif /* POLARSSL_AES_C */
00191 
00192 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
00193           ( POLARSSL_AES_C || POLARSSL_DES_C ) */
00194 
00195 int pem_read_buffer( pem_context *ctx, const char *header, const char *footer,
00196                      const unsigned char *data, const unsigned char *pwd,
00197                      size_t pwdlen, size_t *use_len )
00198 {
00199     int ret, enc;
00200     size_t len;
00201     unsigned char *buf;
00202     const unsigned char *s1, *s2, *end;
00203 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
00204     ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
00205     unsigned char pem_iv[16];
00206     cipher_type_t enc_alg = POLARSSL_CIPHER_NONE;
00207 #else
00208     ((void) pwd);
00209     ((void) pwdlen);
00210 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
00211           ( POLARSSL_AES_C || POLARSSL_DES_C ) */
00212 
00213     if( ctx == NULL )
00214         return( POLARSSL_ERR_PEM_BAD_INPUT_DATA );
00215 
00216     s1 = (unsigned char *) strstr( (const char *) data, header );
00217 
00218     if( s1 == NULL )
00219         return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
00220 
00221     s2 = (unsigned char *) strstr( (const char *) data, footer );
00222 
00223     if( s2 == NULL || s2 <= s1 )
00224         return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
00225 
00226     s1 += strlen( header );
00227     if( *s1 == '\r' ) s1++;
00228     if( *s1 == '\n' ) s1++;
00229     else return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
00230 
00231     end = s2;
00232     end += strlen( footer );
00233     if( *end == '\r' ) end++;
00234     if( *end == '\n' ) end++;
00235     *use_len = end - data;
00236 
00237     enc = 0;
00238 
00239     if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
00240     {
00241 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
00242     ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
00243         enc++;
00244 
00245         s1 += 22;
00246         if( *s1 == '\r' ) s1++;
00247         if( *s1 == '\n' ) s1++;
00248         else return( POLARSSL_ERR_PEM_INVALID_DATA );
00249 
00250 
00251 #if defined(POLARSSL_DES_C)
00252         if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
00253         {
00254             enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC;
00255 
00256             s1 += 23;
00257             if( pem_get_iv( s1, pem_iv, 8 ) != 0 )
00258                 return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
00259 
00260             s1 += 16;
00261         }
00262         else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
00263         {
00264             enc_alg = POLARSSL_CIPHER_DES_CBC;
00265 
00266             s1 += 18;
00267             if( pem_get_iv( s1, pem_iv, 8) != 0 )
00268                 return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
00269 
00270             s1 += 16;
00271         }
00272 #endif /* POLARSSL_DES_C */
00273 
00274 #if defined(POLARSSL_AES_C)
00275         if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
00276         {
00277             if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
00278                 enc_alg = POLARSSL_CIPHER_AES_128_CBC;
00279             else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
00280                 enc_alg = POLARSSL_CIPHER_AES_192_CBC;
00281             else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
00282                 enc_alg = POLARSSL_CIPHER_AES_256_CBC;
00283             else
00284                 return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
00285 
00286             s1 += 22;
00287             if( pem_get_iv( s1, pem_iv, 16 ) != 0 )
00288                 return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
00289 
00290             s1 += 32;
00291         }
00292 #endif /* POLARSSL_AES_C */
00293 
00294         if( enc_alg == POLARSSL_CIPHER_NONE )
00295             return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
00296 
00297         if( *s1 == '\r' ) s1++;
00298         if( *s1 == '\n' ) s1++;
00299         else return( POLARSSL_ERR_PEM_INVALID_DATA );
00300 #else
00301         return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
00302 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
00303           ( POLARSSL_AES_C || POLARSSL_DES_C ) */
00304     }
00305 
00306     len = 0;
00307     ret = base64_decode( NULL, &len, s1, s2 - s1 );
00308 
00309     if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
00310         return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
00311 
00312     if( ( buf = (unsigned char *) polarssl_malloc( len ) ) == NULL )
00313         return( POLARSSL_ERR_PEM_MALLOC_FAILED );
00314 
00315     if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
00316     {
00317         polarssl_free( buf );
00318         return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
00319     }
00320 
00321     if( enc != 0 )
00322     {
00323 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
00324     ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
00325         if( pwd == NULL )
00326         {
00327             polarssl_free( buf );
00328             return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED );
00329         }
00330 
00331 #if defined(POLARSSL_DES_C)
00332         if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC )
00333             pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
00334         else if( enc_alg == POLARSSL_CIPHER_DES_CBC )
00335             pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
00336 #endif /* POLARSSL_DES_C */
00337 
00338 #if defined(POLARSSL_AES_C)
00339         if( enc_alg == POLARSSL_CIPHER_AES_128_CBC )
00340             pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
00341         else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC )
00342             pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
00343         else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC )
00344             pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
00345 #endif /* POLARSSL_AES_C */
00346 
00347         /*
00348          * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
00349          * length bytes (allow 4 to be sure) in all known use cases.
00350          *
00351          * Use that as heurisitic to try detecting password mismatchs.
00352          */
00353         if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
00354         {
00355             polarssl_free( buf );
00356             return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH );
00357         }
00358 #else
00359         polarssl_free( buf );
00360         return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
00361 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
00362           ( POLARSSL_AES_C || POLARSSL_DES_C ) */
00363     }
00364 
00365     ctx->buf  = buf;
00366     ctx->buflen  = len;
00367 
00368     return( 0 );
00369 }
00370 
00371 void pem_free( pem_context *ctx )
00372 {
00373     if( ctx->buf  )
00374         polarssl_free( ctx->buf  );
00375 
00376     if( ctx->info  )
00377         polarssl_free( ctx->info  );
00378 
00379     memset( ctx, 0, sizeof( pem_context ) );
00380 }
00381 #endif /* POLARSSL_PEM_PARSE_C */
00382 
00383 #if defined(POLARSSL_PEM_WRITE_C)
00384 int pem_write_buffer( const char *header, const char *footer,
00385                       const unsigned char *der_data, size_t der_len,
00386                       unsigned char *buf, size_t buf_len, size_t *olen )
00387 {
00388     int ret;
00389     unsigned char *encode_buf, *c, *p = buf;
00390     size_t len = 0, use_len = 0, add_len = 0;
00391 
00392     base64_encode( NULL, &use_len, der_data, der_len );
00393     add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
00394 
00395     if( use_len + add_len > buf_len )
00396     {
00397         *olen = use_len + add_len;
00398         return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
00399     }
00400 
00401     if( ( encode_buf = polarssl_malloc( use_len ) ) == NULL )
00402         return( POLARSSL_ERR_PEM_MALLOC_FAILED );
00403 
00404     if( ( ret = base64_encode( encode_buf, &use_len, der_data,
00405                                der_len ) ) != 0 )
00406     {
00407         polarssl_free( encode_buf );
00408         return( ret );
00409     }
00410 
00411     memcpy( p, header, strlen( header ) );
00412     p += strlen( header );
00413     c = encode_buf;
00414 
00415     while( use_len )
00416     {
00417         len = ( use_len > 64 ) ? 64 : use_len;
00418         memcpy( p, c, len );
00419         use_len -= len;
00420         p += len;
00421         c += len;
00422         *p++ = '\n';
00423     }
00424 
00425     memcpy( p, footer, strlen( footer ) );
00426     p += strlen( footer );
00427 
00428     *p++ = '\0';
00429     *olen = p - buf;
00430 
00431     polarssl_free( encode_buf );
00432     return( 0 );
00433 }
00434 #endif /* POLARSSL_PEM_WRITE_C */
00435 #endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */
00436 
00437