mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
Parent:
0:5b88d5760320
updated based on mbed-os5.15.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /*
kenjiArai 0:5b88d5760320 2 * Privacy Enhanced Mail (PEM) decoding
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
kenjiArai 0:5b88d5760320 5 * SPDX-License-Identifier: Apache-2.0
kenjiArai 0:5b88d5760320 6 *
kenjiArai 0:5b88d5760320 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
kenjiArai 0:5b88d5760320 8 * not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 9 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 10 *
kenjiArai 0:5b88d5760320 11 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 12 *
kenjiArai 0:5b88d5760320 13 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
kenjiArai 0:5b88d5760320 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 16 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 17 * limitations under the License.
kenjiArai 0:5b88d5760320 18 *
kenjiArai 0:5b88d5760320 19 * This file is part of mbed TLS (https://tls.mbed.org)
kenjiArai 0:5b88d5760320 20 */
kenjiArai 0:5b88d5760320 21
kenjiArai 0:5b88d5760320 22 #if !defined(MBEDTLS_CONFIG_FILE)
kenjiArai 0:5b88d5760320 23 #include "mbedtls/config.h"
kenjiArai 0:5b88d5760320 24 #else
kenjiArai 0:5b88d5760320 25 #include MBEDTLS_CONFIG_FILE
kenjiArai 0:5b88d5760320 26 #endif
kenjiArai 0:5b88d5760320 27
kenjiArai 0:5b88d5760320 28 #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
kenjiArai 0:5b88d5760320 29
kenjiArai 0:5b88d5760320 30 #include "mbedtls/pem.h"
kenjiArai 0:5b88d5760320 31 #include "mbedtls/base64.h"
kenjiArai 0:5b88d5760320 32 #include "mbedtls/des.h"
kenjiArai 0:5b88d5760320 33 #include "mbedtls/aes.h"
kenjiArai 0:5b88d5760320 34 #include "mbedtls/md5.h"
kenjiArai 0:5b88d5760320 35 #include "mbedtls/cipher.h"
kenjiArai 0:5b88d5760320 36 #include "mbedtls/platform_util.h"
kenjiArai 0:5b88d5760320 37
kenjiArai 0:5b88d5760320 38 #include <string.h>
kenjiArai 0:5b88d5760320 39
kenjiArai 0:5b88d5760320 40 #if defined(MBEDTLS_PLATFORM_C)
kenjiArai 0:5b88d5760320 41 #include "mbedtls/platform.h"
kenjiArai 0:5b88d5760320 42 #else
kenjiArai 0:5b88d5760320 43 #include <stdlib.h>
kenjiArai 0:5b88d5760320 44 #define mbedtls_calloc calloc
kenjiArai 0:5b88d5760320 45 #define mbedtls_free free
kenjiArai 0:5b88d5760320 46 #endif
kenjiArai 0:5b88d5760320 47
kenjiArai 0:5b88d5760320 48 #if defined(MBEDTLS_PEM_PARSE_C)
kenjiArai 0:5b88d5760320 49 void mbedtls_pem_init( mbedtls_pem_context *ctx )
kenjiArai 0:5b88d5760320 50 {
kenjiArai 0:5b88d5760320 51 memset( ctx, 0, sizeof( mbedtls_pem_context ) );
kenjiArai 0:5b88d5760320 52 }
kenjiArai 0:5b88d5760320 53
kenjiArai 0:5b88d5760320 54 #if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
kenjiArai 0:5b88d5760320 55 ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
kenjiArai 0:5b88d5760320 56 /*
kenjiArai 0:5b88d5760320 57 * Read a 16-byte hex string and convert it to binary
kenjiArai 0:5b88d5760320 58 */
kenjiArai 0:5b88d5760320 59 static int pem_get_iv( const unsigned char *s, unsigned char *iv,
kenjiArai 0:5b88d5760320 60 size_t iv_len )
kenjiArai 0:5b88d5760320 61 {
kenjiArai 0:5b88d5760320 62 size_t i, j, k;
kenjiArai 0:5b88d5760320 63
kenjiArai 0:5b88d5760320 64 memset( iv, 0, iv_len );
kenjiArai 0:5b88d5760320 65
kenjiArai 0:5b88d5760320 66 for( i = 0; i < iv_len * 2; i++, s++ )
kenjiArai 0:5b88d5760320 67 {
kenjiArai 0:5b88d5760320 68 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
kenjiArai 0:5b88d5760320 69 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
kenjiArai 0:5b88d5760320 70 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
kenjiArai 0:5b88d5760320 71 return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
kenjiArai 0:5b88d5760320 72
kenjiArai 0:5b88d5760320 73 k = ( ( i & 1 ) != 0 ) ? j : j << 4;
kenjiArai 0:5b88d5760320 74
kenjiArai 0:5b88d5760320 75 iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
kenjiArai 0:5b88d5760320 76 }
kenjiArai 0:5b88d5760320 77
kenjiArai 0:5b88d5760320 78 return( 0 );
kenjiArai 0:5b88d5760320 79 }
kenjiArai 0:5b88d5760320 80
kenjiArai 0:5b88d5760320 81 static int pem_pbkdf1( unsigned char *key, size_t keylen,
kenjiArai 0:5b88d5760320 82 unsigned char *iv,
kenjiArai 0:5b88d5760320 83 const unsigned char *pwd, size_t pwdlen )
kenjiArai 0:5b88d5760320 84 {
kenjiArai 0:5b88d5760320 85 mbedtls_md5_context md5_ctx;
kenjiArai 0:5b88d5760320 86 unsigned char md5sum[16];
kenjiArai 0:5b88d5760320 87 size_t use_len;
kenjiArai 0:5b88d5760320 88 int ret;
kenjiArai 0:5b88d5760320 89
kenjiArai 0:5b88d5760320 90 mbedtls_md5_init( &md5_ctx );
kenjiArai 0:5b88d5760320 91
kenjiArai 0:5b88d5760320 92 /*
kenjiArai 0:5b88d5760320 93 * key[ 0..15] = MD5(pwd || IV)
kenjiArai 0:5b88d5760320 94 */
kenjiArai 0:5b88d5760320 95 if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 )
kenjiArai 0:5b88d5760320 96 goto exit;
kenjiArai 0:5b88d5760320 97 if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
kenjiArai 0:5b88d5760320 98 goto exit;
kenjiArai 0:5b88d5760320 99 if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 )
kenjiArai 0:5b88d5760320 100 goto exit;
kenjiArai 0:5b88d5760320 101 if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
kenjiArai 0:5b88d5760320 102 goto exit;
kenjiArai 0:5b88d5760320 103
kenjiArai 0:5b88d5760320 104 if( keylen <= 16 )
kenjiArai 0:5b88d5760320 105 {
kenjiArai 0:5b88d5760320 106 memcpy( key, md5sum, keylen );
kenjiArai 0:5b88d5760320 107 goto exit;
kenjiArai 0:5b88d5760320 108 }
kenjiArai 0:5b88d5760320 109
kenjiArai 0:5b88d5760320 110 memcpy( key, md5sum, 16 );
kenjiArai 0:5b88d5760320 111
kenjiArai 0:5b88d5760320 112 /*
kenjiArai 0:5b88d5760320 113 * key[16..23] = MD5(key[ 0..15] || pwd || IV])
kenjiArai 0:5b88d5760320 114 */
kenjiArai 0:5b88d5760320 115 if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 )
kenjiArai 0:5b88d5760320 116 goto exit;
kenjiArai 0:5b88d5760320 117 if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 )
kenjiArai 0:5b88d5760320 118 goto exit;
kenjiArai 0:5b88d5760320 119 if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
kenjiArai 0:5b88d5760320 120 goto exit;
kenjiArai 0:5b88d5760320 121 if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 )
kenjiArai 0:5b88d5760320 122 goto exit;
kenjiArai 0:5b88d5760320 123 if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
kenjiArai 0:5b88d5760320 124 goto exit;
kenjiArai 0:5b88d5760320 125
kenjiArai 0:5b88d5760320 126 use_len = 16;
kenjiArai 0:5b88d5760320 127 if( keylen < 32 )
kenjiArai 0:5b88d5760320 128 use_len = keylen - 16;
kenjiArai 0:5b88d5760320 129
kenjiArai 0:5b88d5760320 130 memcpy( key + 16, md5sum, use_len );
kenjiArai 0:5b88d5760320 131
kenjiArai 0:5b88d5760320 132 exit:
kenjiArai 0:5b88d5760320 133 mbedtls_md5_free( &md5_ctx );
kenjiArai 0:5b88d5760320 134 mbedtls_platform_zeroize( md5sum, 16 );
kenjiArai 0:5b88d5760320 135
kenjiArai 0:5b88d5760320 136 return( ret );
kenjiArai 0:5b88d5760320 137 }
kenjiArai 0:5b88d5760320 138
kenjiArai 0:5b88d5760320 139 #if defined(MBEDTLS_DES_C)
kenjiArai 0:5b88d5760320 140 /*
kenjiArai 0:5b88d5760320 141 * Decrypt with DES-CBC, using PBKDF1 for key derivation
kenjiArai 0:5b88d5760320 142 */
kenjiArai 0:5b88d5760320 143 static int pem_des_decrypt( unsigned char des_iv[8],
kenjiArai 0:5b88d5760320 144 unsigned char *buf, size_t buflen,
kenjiArai 0:5b88d5760320 145 const unsigned char *pwd, size_t pwdlen )
kenjiArai 0:5b88d5760320 146 {
kenjiArai 0:5b88d5760320 147 mbedtls_des_context des_ctx;
kenjiArai 0:5b88d5760320 148 unsigned char des_key[8];
kenjiArai 0:5b88d5760320 149 int ret;
kenjiArai 0:5b88d5760320 150
kenjiArai 0:5b88d5760320 151 mbedtls_des_init( &des_ctx );
kenjiArai 0:5b88d5760320 152
kenjiArai 0:5b88d5760320 153 if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 )
kenjiArai 0:5b88d5760320 154 goto exit;
kenjiArai 0:5b88d5760320 155
kenjiArai 0:5b88d5760320 156 if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 )
kenjiArai 0:5b88d5760320 157 goto exit;
kenjiArai 0:5b88d5760320 158 ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen,
kenjiArai 0:5b88d5760320 159 des_iv, buf, buf );
kenjiArai 0:5b88d5760320 160
kenjiArai 0:5b88d5760320 161 exit:
kenjiArai 0:5b88d5760320 162 mbedtls_des_free( &des_ctx );
kenjiArai 0:5b88d5760320 163 mbedtls_platform_zeroize( des_key, 8 );
kenjiArai 0:5b88d5760320 164
kenjiArai 0:5b88d5760320 165 return( ret );
kenjiArai 0:5b88d5760320 166 }
kenjiArai 0:5b88d5760320 167
kenjiArai 0:5b88d5760320 168 /*
kenjiArai 0:5b88d5760320 169 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
kenjiArai 0:5b88d5760320 170 */
kenjiArai 0:5b88d5760320 171 static int pem_des3_decrypt( unsigned char des3_iv[8],
kenjiArai 0:5b88d5760320 172 unsigned char *buf, size_t buflen,
kenjiArai 0:5b88d5760320 173 const unsigned char *pwd, size_t pwdlen )
kenjiArai 0:5b88d5760320 174 {
kenjiArai 0:5b88d5760320 175 mbedtls_des3_context des3_ctx;
kenjiArai 0:5b88d5760320 176 unsigned char des3_key[24];
kenjiArai 0:5b88d5760320 177 int ret;
kenjiArai 0:5b88d5760320 178
kenjiArai 0:5b88d5760320 179 mbedtls_des3_init( &des3_ctx );
kenjiArai 0:5b88d5760320 180
kenjiArai 0:5b88d5760320 181 if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 )
kenjiArai 0:5b88d5760320 182 goto exit;
kenjiArai 0:5b88d5760320 183
kenjiArai 0:5b88d5760320 184 if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 )
kenjiArai 0:5b88d5760320 185 goto exit;
kenjiArai 0:5b88d5760320 186 ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
kenjiArai 0:5b88d5760320 187 des3_iv, buf, buf );
kenjiArai 0:5b88d5760320 188
kenjiArai 0:5b88d5760320 189 exit:
kenjiArai 0:5b88d5760320 190 mbedtls_des3_free( &des3_ctx );
kenjiArai 0:5b88d5760320 191 mbedtls_platform_zeroize( des3_key, 24 );
kenjiArai 0:5b88d5760320 192
kenjiArai 0:5b88d5760320 193 return( ret );
kenjiArai 0:5b88d5760320 194 }
kenjiArai 0:5b88d5760320 195 #endif /* MBEDTLS_DES_C */
kenjiArai 0:5b88d5760320 196
kenjiArai 0:5b88d5760320 197 #if defined(MBEDTLS_AES_C)
kenjiArai 0:5b88d5760320 198 /*
kenjiArai 0:5b88d5760320 199 * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
kenjiArai 0:5b88d5760320 200 */
kenjiArai 0:5b88d5760320 201 static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
kenjiArai 0:5b88d5760320 202 unsigned char *buf, size_t buflen,
kenjiArai 0:5b88d5760320 203 const unsigned char *pwd, size_t pwdlen )
kenjiArai 0:5b88d5760320 204 {
kenjiArai 0:5b88d5760320 205 mbedtls_aes_context aes_ctx;
kenjiArai 0:5b88d5760320 206 unsigned char aes_key[32];
kenjiArai 0:5b88d5760320 207 int ret;
kenjiArai 0:5b88d5760320 208
kenjiArai 0:5b88d5760320 209 mbedtls_aes_init( &aes_ctx );
kenjiArai 0:5b88d5760320 210
kenjiArai 0:5b88d5760320 211 if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 )
kenjiArai 0:5b88d5760320 212 goto exit;
kenjiArai 0:5b88d5760320 213
kenjiArai 0:5b88d5760320 214 if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 )
kenjiArai 0:5b88d5760320 215 goto exit;
kenjiArai 0:5b88d5760320 216 ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
kenjiArai 0:5b88d5760320 217 aes_iv, buf, buf );
kenjiArai 0:5b88d5760320 218
kenjiArai 0:5b88d5760320 219 exit:
kenjiArai 0:5b88d5760320 220 mbedtls_aes_free( &aes_ctx );
kenjiArai 0:5b88d5760320 221 mbedtls_platform_zeroize( aes_key, keylen );
kenjiArai 0:5b88d5760320 222
kenjiArai 0:5b88d5760320 223 return( ret );
kenjiArai 0:5b88d5760320 224 }
kenjiArai 0:5b88d5760320 225 #endif /* MBEDTLS_AES_C */
kenjiArai 0:5b88d5760320 226
kenjiArai 0:5b88d5760320 227 #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
kenjiArai 0:5b88d5760320 228 ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
kenjiArai 0:5b88d5760320 229
kenjiArai 0:5b88d5760320 230 int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer,
kenjiArai 0:5b88d5760320 231 const unsigned char *data, const unsigned char *pwd,
kenjiArai 0:5b88d5760320 232 size_t pwdlen, size_t *use_len )
kenjiArai 0:5b88d5760320 233 {
kenjiArai 0:5b88d5760320 234 int ret, enc;
kenjiArai 0:5b88d5760320 235 size_t len;
kenjiArai 0:5b88d5760320 236 unsigned char *buf;
kenjiArai 0:5b88d5760320 237 const unsigned char *s1, *s2, *end;
kenjiArai 0:5b88d5760320 238 #if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
kenjiArai 0:5b88d5760320 239 ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
kenjiArai 0:5b88d5760320 240 unsigned char pem_iv[16];
kenjiArai 0:5b88d5760320 241 mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE;
kenjiArai 0:5b88d5760320 242 #else
kenjiArai 0:5b88d5760320 243 ((void) pwd);
kenjiArai 0:5b88d5760320 244 ((void) pwdlen);
kenjiArai 0:5b88d5760320 245 #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
kenjiArai 0:5b88d5760320 246 ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
kenjiArai 0:5b88d5760320 247
kenjiArai 0:5b88d5760320 248 if( ctx == NULL )
kenjiArai 0:5b88d5760320 249 return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA );
kenjiArai 0:5b88d5760320 250
kenjiArai 0:5b88d5760320 251 s1 = (unsigned char *) strstr( (const char *) data, header );
kenjiArai 0:5b88d5760320 252
kenjiArai 0:5b88d5760320 253 if( s1 == NULL )
kenjiArai 0:5b88d5760320 254 return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
kenjiArai 0:5b88d5760320 255
kenjiArai 0:5b88d5760320 256 s2 = (unsigned char *) strstr( (const char *) data, footer );
kenjiArai 0:5b88d5760320 257
kenjiArai 0:5b88d5760320 258 if( s2 == NULL || s2 <= s1 )
kenjiArai 0:5b88d5760320 259 return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
kenjiArai 0:5b88d5760320 260
kenjiArai 0:5b88d5760320 261 s1 += strlen( header );
kenjiArai 0:5b88d5760320 262 if( *s1 == ' ' ) s1++;
kenjiArai 0:5b88d5760320 263 if( *s1 == '\r' ) s1++;
kenjiArai 0:5b88d5760320 264 if( *s1 == '\n' ) s1++;
kenjiArai 0:5b88d5760320 265 else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
kenjiArai 0:5b88d5760320 266
kenjiArai 0:5b88d5760320 267 end = s2;
kenjiArai 0:5b88d5760320 268 end += strlen( footer );
kenjiArai 0:5b88d5760320 269 if( *end == ' ' ) end++;
kenjiArai 0:5b88d5760320 270 if( *end == '\r' ) end++;
kenjiArai 0:5b88d5760320 271 if( *end == '\n' ) end++;
kenjiArai 0:5b88d5760320 272 *use_len = end - data;
kenjiArai 0:5b88d5760320 273
kenjiArai 0:5b88d5760320 274 enc = 0;
kenjiArai 0:5b88d5760320 275
kenjiArai 0:5b88d5760320 276 if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
kenjiArai 0:5b88d5760320 277 {
kenjiArai 0:5b88d5760320 278 #if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
kenjiArai 0:5b88d5760320 279 ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
kenjiArai 0:5b88d5760320 280 enc++;
kenjiArai 0:5b88d5760320 281
kenjiArai 0:5b88d5760320 282 s1 += 22;
kenjiArai 0:5b88d5760320 283 if( *s1 == '\r' ) s1++;
kenjiArai 0:5b88d5760320 284 if( *s1 == '\n' ) s1++;
kenjiArai 0:5b88d5760320 285 else return( MBEDTLS_ERR_PEM_INVALID_DATA );
kenjiArai 0:5b88d5760320 286
kenjiArai 0:5b88d5760320 287
kenjiArai 0:5b88d5760320 288 #if defined(MBEDTLS_DES_C)
kenjiArai 0:5b88d5760320 289 if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
kenjiArai 0:5b88d5760320 290 {
kenjiArai 0:5b88d5760320 291 enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC;
kenjiArai 0:5b88d5760320 292
kenjiArai 0:5b88d5760320 293 s1 += 23;
kenjiArai 0:5b88d5760320 294 if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 )
kenjiArai 0:5b88d5760320 295 return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
kenjiArai 0:5b88d5760320 296
kenjiArai 0:5b88d5760320 297 s1 += 16;
kenjiArai 0:5b88d5760320 298 }
kenjiArai 0:5b88d5760320 299 else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
kenjiArai 0:5b88d5760320 300 {
kenjiArai 0:5b88d5760320 301 enc_alg = MBEDTLS_CIPHER_DES_CBC;
kenjiArai 0:5b88d5760320 302
kenjiArai 0:5b88d5760320 303 s1 += 18;
kenjiArai 0:5b88d5760320 304 if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 )
kenjiArai 0:5b88d5760320 305 return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
kenjiArai 0:5b88d5760320 306
kenjiArai 0:5b88d5760320 307 s1 += 16;
kenjiArai 0:5b88d5760320 308 }
kenjiArai 0:5b88d5760320 309 #endif /* MBEDTLS_DES_C */
kenjiArai 0:5b88d5760320 310
kenjiArai 0:5b88d5760320 311 #if defined(MBEDTLS_AES_C)
kenjiArai 0:5b88d5760320 312 if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
kenjiArai 0:5b88d5760320 313 {
kenjiArai 0:5b88d5760320 314 if( s2 - s1 < 22 )
kenjiArai 0:5b88d5760320 315 return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
kenjiArai 0:5b88d5760320 316 else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
kenjiArai 0:5b88d5760320 317 enc_alg = MBEDTLS_CIPHER_AES_128_CBC;
kenjiArai 0:5b88d5760320 318 else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
kenjiArai 0:5b88d5760320 319 enc_alg = MBEDTLS_CIPHER_AES_192_CBC;
kenjiArai 0:5b88d5760320 320 else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
kenjiArai 0:5b88d5760320 321 enc_alg = MBEDTLS_CIPHER_AES_256_CBC;
kenjiArai 0:5b88d5760320 322 else
kenjiArai 0:5b88d5760320 323 return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
kenjiArai 0:5b88d5760320 324
kenjiArai 0:5b88d5760320 325 s1 += 22;
kenjiArai 0:5b88d5760320 326 if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 )
kenjiArai 0:5b88d5760320 327 return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
kenjiArai 0:5b88d5760320 328
kenjiArai 0:5b88d5760320 329 s1 += 32;
kenjiArai 0:5b88d5760320 330 }
kenjiArai 0:5b88d5760320 331 #endif /* MBEDTLS_AES_C */
kenjiArai 0:5b88d5760320 332
kenjiArai 0:5b88d5760320 333 if( enc_alg == MBEDTLS_CIPHER_NONE )
kenjiArai 0:5b88d5760320 334 return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
kenjiArai 0:5b88d5760320 335
kenjiArai 0:5b88d5760320 336 if( *s1 == '\r' ) s1++;
kenjiArai 0:5b88d5760320 337 if( *s1 == '\n' ) s1++;
kenjiArai 0:5b88d5760320 338 else return( MBEDTLS_ERR_PEM_INVALID_DATA );
kenjiArai 0:5b88d5760320 339 #else
kenjiArai 0:5b88d5760320 340 return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
kenjiArai 0:5b88d5760320 341 #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
kenjiArai 0:5b88d5760320 342 ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
kenjiArai 0:5b88d5760320 343 }
kenjiArai 0:5b88d5760320 344
kenjiArai 0:5b88d5760320 345 if( s1 >= s2 )
kenjiArai 0:5b88d5760320 346 return( MBEDTLS_ERR_PEM_INVALID_DATA );
kenjiArai 0:5b88d5760320 347
kenjiArai 0:5b88d5760320 348 ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 );
kenjiArai 0:5b88d5760320 349
kenjiArai 0:5b88d5760320 350 if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER )
kenjiArai 0:5b88d5760320 351 return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
kenjiArai 0:5b88d5760320 352
kenjiArai 0:5b88d5760320 353 if( ( buf = mbedtls_calloc( 1, len ) ) == NULL )
kenjiArai 0:5b88d5760320 354 return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
kenjiArai 0:5b88d5760320 355
kenjiArai 0:5b88d5760320 356 if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 )
kenjiArai 0:5b88d5760320 357 {
kenjiArai 0:5b88d5760320 358 mbedtls_platform_zeroize( buf, len );
kenjiArai 0:5b88d5760320 359 mbedtls_free( buf );
kenjiArai 0:5b88d5760320 360 return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
kenjiArai 0:5b88d5760320 361 }
kenjiArai 0:5b88d5760320 362
kenjiArai 0:5b88d5760320 363 if( enc != 0 )
kenjiArai 0:5b88d5760320 364 {
kenjiArai 0:5b88d5760320 365 #if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
kenjiArai 0:5b88d5760320 366 ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
kenjiArai 0:5b88d5760320 367 if( pwd == NULL )
kenjiArai 0:5b88d5760320 368 {
kenjiArai 0:5b88d5760320 369 mbedtls_platform_zeroize( buf, len );
kenjiArai 0:5b88d5760320 370 mbedtls_free( buf );
kenjiArai 0:5b88d5760320 371 return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED );
kenjiArai 0:5b88d5760320 372 }
kenjiArai 0:5b88d5760320 373
kenjiArai 0:5b88d5760320 374 ret = 0;
kenjiArai 0:5b88d5760320 375
kenjiArai 0:5b88d5760320 376 #if defined(MBEDTLS_DES_C)
kenjiArai 0:5b88d5760320 377 if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC )
kenjiArai 0:5b88d5760320 378 ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
kenjiArai 0:5b88d5760320 379 else if( enc_alg == MBEDTLS_CIPHER_DES_CBC )
kenjiArai 0:5b88d5760320 380 ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
kenjiArai 0:5b88d5760320 381 #endif /* MBEDTLS_DES_C */
kenjiArai 0:5b88d5760320 382
kenjiArai 0:5b88d5760320 383 #if defined(MBEDTLS_AES_C)
kenjiArai 0:5b88d5760320 384 if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC )
kenjiArai 0:5b88d5760320 385 ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
kenjiArai 0:5b88d5760320 386 else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC )
kenjiArai 0:5b88d5760320 387 ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
kenjiArai 0:5b88d5760320 388 else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC )
kenjiArai 0:5b88d5760320 389 ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
kenjiArai 0:5b88d5760320 390 #endif /* MBEDTLS_AES_C */
kenjiArai 0:5b88d5760320 391
kenjiArai 0:5b88d5760320 392 if( ret != 0 )
kenjiArai 0:5b88d5760320 393 {
kenjiArai 0:5b88d5760320 394 mbedtls_free( buf );
kenjiArai 0:5b88d5760320 395 return( ret );
kenjiArai 0:5b88d5760320 396 }
kenjiArai 0:5b88d5760320 397
kenjiArai 0:5b88d5760320 398 /*
kenjiArai 0:5b88d5760320 399 * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
kenjiArai 0:5b88d5760320 400 * length bytes (allow 4 to be sure) in all known use cases.
kenjiArai 0:5b88d5760320 401 *
kenjiArai 0:5b88d5760320 402 * Use that as a heuristic to try to detect password mismatches.
kenjiArai 0:5b88d5760320 403 */
kenjiArai 0:5b88d5760320 404 if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
kenjiArai 0:5b88d5760320 405 {
kenjiArai 0:5b88d5760320 406 mbedtls_platform_zeroize( buf, len );
kenjiArai 0:5b88d5760320 407 mbedtls_free( buf );
kenjiArai 0:5b88d5760320 408 return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH );
kenjiArai 0:5b88d5760320 409 }
kenjiArai 0:5b88d5760320 410 #else
kenjiArai 0:5b88d5760320 411 mbedtls_platform_zeroize( buf, len );
kenjiArai 0:5b88d5760320 412 mbedtls_free( buf );
kenjiArai 0:5b88d5760320 413 return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
kenjiArai 0:5b88d5760320 414 #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
kenjiArai 0:5b88d5760320 415 ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
kenjiArai 0:5b88d5760320 416 }
kenjiArai 0:5b88d5760320 417
kenjiArai 0:5b88d5760320 418 ctx->buf = buf;
kenjiArai 0:5b88d5760320 419 ctx->buflen = len;
kenjiArai 0:5b88d5760320 420
kenjiArai 0:5b88d5760320 421 return( 0 );
kenjiArai 0:5b88d5760320 422 }
kenjiArai 0:5b88d5760320 423
kenjiArai 0:5b88d5760320 424 void mbedtls_pem_free( mbedtls_pem_context *ctx )
kenjiArai 0:5b88d5760320 425 {
kenjiArai 0:5b88d5760320 426 if ( ctx->buf != NULL )
kenjiArai 0:5b88d5760320 427 {
kenjiArai 0:5b88d5760320 428 mbedtls_platform_zeroize( ctx->buf, ctx->buflen );
kenjiArai 0:5b88d5760320 429 mbedtls_free( ctx->buf );
kenjiArai 0:5b88d5760320 430 }
kenjiArai 0:5b88d5760320 431 mbedtls_free( ctx->info );
kenjiArai 0:5b88d5760320 432
kenjiArai 0:5b88d5760320 433 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) );
kenjiArai 0:5b88d5760320 434 }
kenjiArai 0:5b88d5760320 435 #endif /* MBEDTLS_PEM_PARSE_C */
kenjiArai 0:5b88d5760320 436
kenjiArai 0:5b88d5760320 437 #if defined(MBEDTLS_PEM_WRITE_C)
kenjiArai 0:5b88d5760320 438 int mbedtls_pem_write_buffer( const char *header, const char *footer,
kenjiArai 0:5b88d5760320 439 const unsigned char *der_data, size_t der_len,
kenjiArai 0:5b88d5760320 440 unsigned char *buf, size_t buf_len, size_t *olen )
kenjiArai 0:5b88d5760320 441 {
kenjiArai 0:5b88d5760320 442 int ret;
kenjiArai 0:5b88d5760320 443 unsigned char *encode_buf = NULL, *c, *p = buf;
kenjiArai 0:5b88d5760320 444 size_t len = 0, use_len, add_len = 0;
kenjiArai 0:5b88d5760320 445
kenjiArai 0:5b88d5760320 446 mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len );
kenjiArai 0:5b88d5760320 447 add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
kenjiArai 0:5b88d5760320 448
kenjiArai 0:5b88d5760320 449 if( use_len + add_len > buf_len )
kenjiArai 0:5b88d5760320 450 {
kenjiArai 0:5b88d5760320 451 *olen = use_len + add_len;
kenjiArai 0:5b88d5760320 452 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
kenjiArai 0:5b88d5760320 453 }
kenjiArai 0:5b88d5760320 454
kenjiArai 0:5b88d5760320 455 if( use_len != 0 &&
kenjiArai 0:5b88d5760320 456 ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) )
kenjiArai 0:5b88d5760320 457 return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
kenjiArai 0:5b88d5760320 458
kenjiArai 0:5b88d5760320 459 if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data,
kenjiArai 0:5b88d5760320 460 der_len ) ) != 0 )
kenjiArai 0:5b88d5760320 461 {
kenjiArai 0:5b88d5760320 462 mbedtls_free( encode_buf );
kenjiArai 0:5b88d5760320 463 return( ret );
kenjiArai 0:5b88d5760320 464 }
kenjiArai 0:5b88d5760320 465
kenjiArai 0:5b88d5760320 466 memcpy( p, header, strlen( header ) );
kenjiArai 0:5b88d5760320 467 p += strlen( header );
kenjiArai 0:5b88d5760320 468 c = encode_buf;
kenjiArai 0:5b88d5760320 469
kenjiArai 0:5b88d5760320 470 while( use_len )
kenjiArai 0:5b88d5760320 471 {
kenjiArai 0:5b88d5760320 472 len = ( use_len > 64 ) ? 64 : use_len;
kenjiArai 0:5b88d5760320 473 memcpy( p, c, len );
kenjiArai 0:5b88d5760320 474 use_len -= len;
kenjiArai 0:5b88d5760320 475 p += len;
kenjiArai 0:5b88d5760320 476 c += len;
kenjiArai 0:5b88d5760320 477 *p++ = '\n';
kenjiArai 0:5b88d5760320 478 }
kenjiArai 0:5b88d5760320 479
kenjiArai 0:5b88d5760320 480 memcpy( p, footer, strlen( footer ) );
kenjiArai 0:5b88d5760320 481 p += strlen( footer );
kenjiArai 0:5b88d5760320 482
kenjiArai 0:5b88d5760320 483 *p++ = '\0';
kenjiArai 0:5b88d5760320 484 *olen = p - buf;
kenjiArai 0:5b88d5760320 485
kenjiArai 0:5b88d5760320 486 mbedtls_free( encode_buf );
kenjiArai 0:5b88d5760320 487 return( 0 );
kenjiArai 0:5b88d5760320 488 }
kenjiArai 0:5b88d5760320 489 #endif /* MBEDTLS_PEM_WRITE_C */
kenjiArai 0:5b88d5760320 490 #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */