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

Dependencies:   mbed

Committer:
HannesTschofenig
Date:
Thu Sep 27 06:34:22 2018 +0000
Revision:
0:796d0f61a05b
Example AES-GCM test program

Who changed what in which revision?

UserRevisionLine numberNew contents of line
HannesTschofenig 0:796d0f61a05b 1 /**
HannesTschofenig 0:796d0f61a05b 2 * \file cipher.c
HannesTschofenig 0:796d0f61a05b 3 *
HannesTschofenig 0:796d0f61a05b 4 * \brief Generic cipher wrapper for PolarSSL
HannesTschofenig 0:796d0f61a05b 5 *
HannesTschofenig 0:796d0f61a05b 6 * \author Adriaan de Jong <dejong@fox-it.com>
HannesTschofenig 0:796d0f61a05b 7 *
HannesTschofenig 0:796d0f61a05b 8 * Copyright (C) 2006-2014, Brainspark B.V.
HannesTschofenig 0:796d0f61a05b 9 *
HannesTschofenig 0:796d0f61a05b 10 * This file is part of PolarSSL (http://www.polarssl.org)
HannesTschofenig 0:796d0f61a05b 11 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
HannesTschofenig 0:796d0f61a05b 12 *
HannesTschofenig 0:796d0f61a05b 13 * All rights reserved.
HannesTschofenig 0:796d0f61a05b 14 *
HannesTschofenig 0:796d0f61a05b 15 * This program is free software; you can redistribute it and/or modify
HannesTschofenig 0:796d0f61a05b 16 * it under the terms of the GNU General Public License as published by
HannesTschofenig 0:796d0f61a05b 17 * the Free Software Foundation; either version 2 of the License, or
HannesTschofenig 0:796d0f61a05b 18 * (at your option) any later version.
HannesTschofenig 0:796d0f61a05b 19 *
HannesTschofenig 0:796d0f61a05b 20 * This program is distributed in the hope that it will be useful,
HannesTschofenig 0:796d0f61a05b 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
HannesTschofenig 0:796d0f61a05b 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
HannesTschofenig 0:796d0f61a05b 23 * GNU General Public License for more details.
HannesTschofenig 0:796d0f61a05b 24 *
HannesTschofenig 0:796d0f61a05b 25 * You should have received a copy of the GNU General Public License along
HannesTschofenig 0:796d0f61a05b 26 * with this program; if not, write to the Free Software Foundation, Inc.,
HannesTschofenig 0:796d0f61a05b 27 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
HannesTschofenig 0:796d0f61a05b 28 */
HannesTschofenig 0:796d0f61a05b 29
HannesTschofenig 0:796d0f61a05b 30 #if !defined(POLARSSL_CONFIG_FILE)
HannesTschofenig 0:796d0f61a05b 31 #include "polarssl/config.h"
HannesTschofenig 0:796d0f61a05b 32 #else
HannesTschofenig 0:796d0f61a05b 33 #include POLARSSL_CONFIG_FILE
HannesTschofenig 0:796d0f61a05b 34 #endif
HannesTschofenig 0:796d0f61a05b 35
HannesTschofenig 0:796d0f61a05b 36 #if defined(POLARSSL_CIPHER_C)
HannesTschofenig 0:796d0f61a05b 37
HannesTschofenig 0:796d0f61a05b 38 #include "polarssl/cipher.h"
HannesTschofenig 0:796d0f61a05b 39 #include "polarssl/cipher_wrap.h"
HannesTschofenig 0:796d0f61a05b 40
HannesTschofenig 0:796d0f61a05b 41 #if defined(POLARSSL_GCM_C)
HannesTschofenig 0:796d0f61a05b 42 #include "polarssl/gcm.h"
HannesTschofenig 0:796d0f61a05b 43 #endif
HannesTschofenig 0:796d0f61a05b 44
HannesTschofenig 0:796d0f61a05b 45 #include <stdlib.h>
HannesTschofenig 0:796d0f61a05b 46
HannesTschofenig 0:796d0f61a05b 47 #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
HannesTschofenig 0:796d0f61a05b 48 #define POLARSSL_CIPHER_MODE_STREAM
HannesTschofenig 0:796d0f61a05b 49 #endif
HannesTschofenig 0:796d0f61a05b 50
HannesTschofenig 0:796d0f61a05b 51 #if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
HannesTschofenig 0:796d0f61a05b 52 !defined(EFI32)
HannesTschofenig 0:796d0f61a05b 53 #define strcasecmp _stricmp
HannesTschofenig 0:796d0f61a05b 54 #endif
HannesTschofenig 0:796d0f61a05b 55
HannesTschofenig 0:796d0f61a05b 56 static int supported_init = 0;
HannesTschofenig 0:796d0f61a05b 57
HannesTschofenig 0:796d0f61a05b 58 const int *cipher_list( void )
HannesTschofenig 0:796d0f61a05b 59 {
HannesTschofenig 0:796d0f61a05b 60 const cipher_definition_t *def;
HannesTschofenig 0:796d0f61a05b 61 int *type;
HannesTschofenig 0:796d0f61a05b 62
HannesTschofenig 0:796d0f61a05b 63 if( ! supported_init )
HannesTschofenig 0:796d0f61a05b 64 {
HannesTschofenig 0:796d0f61a05b 65 def = cipher_definitions;
HannesTschofenig 0:796d0f61a05b 66 type = supported_ciphers;
HannesTschofenig 0:796d0f61a05b 67
HannesTschofenig 0:796d0f61a05b 68 while( def->type != 0 )
HannesTschofenig 0:796d0f61a05b 69 *type++ = (*def++).type;
HannesTschofenig 0:796d0f61a05b 70
HannesTschofenig 0:796d0f61a05b 71 *type = 0;
HannesTschofenig 0:796d0f61a05b 72
HannesTschofenig 0:796d0f61a05b 73 supported_init = 1;
HannesTschofenig 0:796d0f61a05b 74 }
HannesTschofenig 0:796d0f61a05b 75
HannesTschofenig 0:796d0f61a05b 76 return supported_ciphers;
HannesTschofenig 0:796d0f61a05b 77 }
HannesTschofenig 0:796d0f61a05b 78
HannesTschofenig 0:796d0f61a05b 79 const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type )
HannesTschofenig 0:796d0f61a05b 80 {
HannesTschofenig 0:796d0f61a05b 81 const cipher_definition_t *def;
HannesTschofenig 0:796d0f61a05b 82
HannesTschofenig 0:796d0f61a05b 83 for( def = cipher_definitions; def->info != NULL; def++ )
HannesTschofenig 0:796d0f61a05b 84 if( def->type == cipher_type )
HannesTschofenig 0:796d0f61a05b 85 return( def->info );
HannesTschofenig 0:796d0f61a05b 86
HannesTschofenig 0:796d0f61a05b 87 return NULL;
HannesTschofenig 0:796d0f61a05b 88 }
HannesTschofenig 0:796d0f61a05b 89
HannesTschofenig 0:796d0f61a05b 90 const cipher_info_t *cipher_info_from_string( const char *cipher_name )
HannesTschofenig 0:796d0f61a05b 91 {
HannesTschofenig 0:796d0f61a05b 92 const cipher_definition_t *def;
HannesTschofenig 0:796d0f61a05b 93
HannesTschofenig 0:796d0f61a05b 94 if( NULL == cipher_name )
HannesTschofenig 0:796d0f61a05b 95 return NULL;
HannesTschofenig 0:796d0f61a05b 96
HannesTschofenig 0:796d0f61a05b 97 for( def = cipher_definitions; def->info != NULL; def++ )
HannesTschofenig 0:796d0f61a05b 98 if( ! strcasecmp( def->info->name, cipher_name ) )
HannesTschofenig 0:796d0f61a05b 99 return( def->info );
HannesTschofenig 0:796d0f61a05b 100
HannesTschofenig 0:796d0f61a05b 101 return NULL;
HannesTschofenig 0:796d0f61a05b 102 }
HannesTschofenig 0:796d0f61a05b 103
HannesTschofenig 0:796d0f61a05b 104 const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id,
HannesTschofenig 0:796d0f61a05b 105 int key_length,
HannesTschofenig 0:796d0f61a05b 106 const cipher_mode_t mode )
HannesTschofenig 0:796d0f61a05b 107 {
HannesTschofenig 0:796d0f61a05b 108 const cipher_definition_t *def;
HannesTschofenig 0:796d0f61a05b 109
HannesTschofenig 0:796d0f61a05b 110 for( def = cipher_definitions; def->info != NULL; def++ )
HannesTschofenig 0:796d0f61a05b 111 if( def->info->base->cipher == cipher_id &&
HannesTschofenig 0:796d0f61a05b 112 def->info->key_length == (unsigned) key_length &&
HannesTschofenig 0:796d0f61a05b 113 def->info->mode == mode )
HannesTschofenig 0:796d0f61a05b 114 return( def->info );
HannesTschofenig 0:796d0f61a05b 115
HannesTschofenig 0:796d0f61a05b 116 return NULL;
HannesTschofenig 0:796d0f61a05b 117 }
HannesTschofenig 0:796d0f61a05b 118
HannesTschofenig 0:796d0f61a05b 119 int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info )
HannesTschofenig 0:796d0f61a05b 120 {
HannesTschofenig 0:796d0f61a05b 121 if( NULL == cipher_info || NULL == ctx )
HannesTschofenig 0:796d0f61a05b 122 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 123
HannesTschofenig 0:796d0f61a05b 124 memset( ctx, 0, sizeof( cipher_context_t ) );
HannesTschofenig 0:796d0f61a05b 125
HannesTschofenig 0:796d0f61a05b 126 if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
HannesTschofenig 0:796d0f61a05b 127 return POLARSSL_ERR_CIPHER_ALLOC_FAILED;
HannesTschofenig 0:796d0f61a05b 128
HannesTschofenig 0:796d0f61a05b 129 ctx->cipher_info = cipher_info;
HannesTschofenig 0:796d0f61a05b 130
HannesTschofenig 0:796d0f61a05b 131 #if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
HannesTschofenig 0:796d0f61a05b 132 /*
HannesTschofenig 0:796d0f61a05b 133 * Ignore possible errors caused by a cipher mode that doesn't use padding
HannesTschofenig 0:796d0f61a05b 134 */
HannesTschofenig 0:796d0f61a05b 135 #if defined(POLARSSL_CIPHER_PADDING_PKCS7)
HannesTschofenig 0:796d0f61a05b 136 (void) cipher_set_padding_mode( ctx, POLARSSL_PADDING_PKCS7 );
HannesTschofenig 0:796d0f61a05b 137 #else
HannesTschofenig 0:796d0f61a05b 138 (void) cipher_set_padding_mode( ctx, POLARSSL_PADDING_NONE );
HannesTschofenig 0:796d0f61a05b 139 #endif
HannesTschofenig 0:796d0f61a05b 140 #endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
HannesTschofenig 0:796d0f61a05b 141
HannesTschofenig 0:796d0f61a05b 142 return 0;
HannesTschofenig 0:796d0f61a05b 143 }
HannesTschofenig 0:796d0f61a05b 144
HannesTschofenig 0:796d0f61a05b 145 int cipher_free_ctx( cipher_context_t *ctx )
HannesTschofenig 0:796d0f61a05b 146 {
HannesTschofenig 0:796d0f61a05b 147 if( ctx == NULL || ctx->cipher_info == NULL )
HannesTschofenig 0:796d0f61a05b 148 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 149
HannesTschofenig 0:796d0f61a05b 150 ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
HannesTschofenig 0:796d0f61a05b 151
HannesTschofenig 0:796d0f61a05b 152 return 0;
HannesTschofenig 0:796d0f61a05b 153 }
HannesTschofenig 0:796d0f61a05b 154
HannesTschofenig 0:796d0f61a05b 155 int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
HannesTschofenig 0:796d0f61a05b 156 int key_length, const operation_t operation )
HannesTschofenig 0:796d0f61a05b 157 {
HannesTschofenig 0:796d0f61a05b 158 if( NULL == ctx || NULL == ctx->cipher_info )
HannesTschofenig 0:796d0f61a05b 159 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 160
HannesTschofenig 0:796d0f61a05b 161 if( (int) ctx->cipher_info->key_length != key_length )
HannesTschofenig 0:796d0f61a05b 162 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 163
HannesTschofenig 0:796d0f61a05b 164 ctx->key_length = key_length;
HannesTschofenig 0:796d0f61a05b 165 ctx->operation = operation;
HannesTschofenig 0:796d0f61a05b 166
HannesTschofenig 0:796d0f61a05b 167 /*
HannesTschofenig 0:796d0f61a05b 168 * For CFB and CTR mode always use the encryption key schedule
HannesTschofenig 0:796d0f61a05b 169 */
HannesTschofenig 0:796d0f61a05b 170 if( POLARSSL_ENCRYPT == operation ||
HannesTschofenig 0:796d0f61a05b 171 POLARSSL_MODE_CFB == ctx->cipher_info->mode ||
HannesTschofenig 0:796d0f61a05b 172 POLARSSL_MODE_CTR == ctx->cipher_info->mode )
HannesTschofenig 0:796d0f61a05b 173 {
HannesTschofenig 0:796d0f61a05b 174 return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
HannesTschofenig 0:796d0f61a05b 175 ctx->key_length );
HannesTschofenig 0:796d0f61a05b 176 }
HannesTschofenig 0:796d0f61a05b 177
HannesTschofenig 0:796d0f61a05b 178 if( POLARSSL_DECRYPT == operation )
HannesTschofenig 0:796d0f61a05b 179 return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
HannesTschofenig 0:796d0f61a05b 180 ctx->key_length );
HannesTschofenig 0:796d0f61a05b 181
HannesTschofenig 0:796d0f61a05b 182 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 183 }
HannesTschofenig 0:796d0f61a05b 184
HannesTschofenig 0:796d0f61a05b 185 int cipher_set_iv( cipher_context_t *ctx,
HannesTschofenig 0:796d0f61a05b 186 const unsigned char *iv, size_t iv_len )
HannesTschofenig 0:796d0f61a05b 187 {
HannesTschofenig 0:796d0f61a05b 188 size_t actual_iv_size;
HannesTschofenig 0:796d0f61a05b 189
HannesTschofenig 0:796d0f61a05b 190 if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
HannesTschofenig 0:796d0f61a05b 191 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 192
HannesTschofenig 0:796d0f61a05b 193 /* avoid buffer overflow in ctx->iv */
HannesTschofenig 0:796d0f61a05b 194 if( iv_len > POLARSSL_MAX_IV_LENGTH )
HannesTschofenig 0:796d0f61a05b 195 return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
HannesTschofenig 0:796d0f61a05b 196
HannesTschofenig 0:796d0f61a05b 197 if( ctx->cipher_info->accepts_variable_iv_size )
HannesTschofenig 0:796d0f61a05b 198 actual_iv_size = iv_len;
HannesTschofenig 0:796d0f61a05b 199 else
HannesTschofenig 0:796d0f61a05b 200 {
HannesTschofenig 0:796d0f61a05b 201 actual_iv_size = ctx->cipher_info->iv_size;
HannesTschofenig 0:796d0f61a05b 202
HannesTschofenig 0:796d0f61a05b 203 /* avoid reading past the end of input buffer */
HannesTschofenig 0:796d0f61a05b 204 if( actual_iv_size > iv_len )
HannesTschofenig 0:796d0f61a05b 205 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 206 }
HannesTschofenig 0:796d0f61a05b 207
HannesTschofenig 0:796d0f61a05b 208 memcpy( ctx->iv, iv, actual_iv_size );
HannesTschofenig 0:796d0f61a05b 209 ctx->iv_size = actual_iv_size;
HannesTschofenig 0:796d0f61a05b 210
HannesTschofenig 0:796d0f61a05b 211 return 0;
HannesTschofenig 0:796d0f61a05b 212 }
HannesTschofenig 0:796d0f61a05b 213
HannesTschofenig 0:796d0f61a05b 214 int cipher_reset( cipher_context_t *ctx )
HannesTschofenig 0:796d0f61a05b 215 {
HannesTschofenig 0:796d0f61a05b 216 if( NULL == ctx || NULL == ctx->cipher_info )
HannesTschofenig 0:796d0f61a05b 217 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 218
HannesTschofenig 0:796d0f61a05b 219 ctx->unprocessed_len = 0;
HannesTschofenig 0:796d0f61a05b 220
HannesTschofenig 0:796d0f61a05b 221 return 0;
HannesTschofenig 0:796d0f61a05b 222 }
HannesTschofenig 0:796d0f61a05b 223
HannesTschofenig 0:796d0f61a05b 224 #if defined(POLARSSL_CIPHER_MODE_AEAD)
HannesTschofenig 0:796d0f61a05b 225 int cipher_update_ad( cipher_context_t *ctx,
HannesTschofenig 0:796d0f61a05b 226 const unsigned char *ad, size_t ad_len )
HannesTschofenig 0:796d0f61a05b 227 {
HannesTschofenig 0:796d0f61a05b 228 if( NULL == ctx || NULL == ctx->cipher_info )
HannesTschofenig 0:796d0f61a05b 229 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 230
HannesTschofenig 0:796d0f61a05b 231 #if defined(POLARSSL_GCM_C)
HannesTschofenig 0:796d0f61a05b 232 if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
HannesTschofenig 0:796d0f61a05b 233 {
HannesTschofenig 0:796d0f61a05b 234 return gcm_starts( (gcm_context *) ctx->cipher_ctx, ctx->operation,
HannesTschofenig 0:796d0f61a05b 235 ctx->iv, ctx->iv_size, ad, ad_len );
HannesTschofenig 0:796d0f61a05b 236 }
HannesTschofenig 0:796d0f61a05b 237 #endif
HannesTschofenig 0:796d0f61a05b 238
HannesTschofenig 0:796d0f61a05b 239 return 0;
HannesTschofenig 0:796d0f61a05b 240 }
HannesTschofenig 0:796d0f61a05b 241 #endif /* POLARSSL_CIPHER_MODE_AEAD */
HannesTschofenig 0:796d0f61a05b 242
HannesTschofenig 0:796d0f61a05b 243 int cipher_update( cipher_context_t *ctx, const unsigned char *input,
HannesTschofenig 0:796d0f61a05b 244 size_t ilen, unsigned char *output, size_t *olen )
HannesTschofenig 0:796d0f61a05b 245 {
HannesTschofenig 0:796d0f61a05b 246 int ret;
HannesTschofenig 0:796d0f61a05b 247
HannesTschofenig 0:796d0f61a05b 248 if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
HannesTschofenig 0:796d0f61a05b 249 {
HannesTschofenig 0:796d0f61a05b 250 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 251 }
HannesTschofenig 0:796d0f61a05b 252
HannesTschofenig 0:796d0f61a05b 253 *olen = 0;
HannesTschofenig 0:796d0f61a05b 254
HannesTschofenig 0:796d0f61a05b 255 if( ctx->cipher_info->mode == POLARSSL_MODE_ECB )
HannesTschofenig 0:796d0f61a05b 256 {
HannesTschofenig 0:796d0f61a05b 257 if( ilen != cipher_get_block_size( ctx ) )
HannesTschofenig 0:796d0f61a05b 258 return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
HannesTschofenig 0:796d0f61a05b 259
HannesTschofenig 0:796d0f61a05b 260 *olen = ilen;
HannesTschofenig 0:796d0f61a05b 261
HannesTschofenig 0:796d0f61a05b 262 if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
HannesTschofenig 0:796d0f61a05b 263 ctx->operation, input, output ) ) )
HannesTschofenig 0:796d0f61a05b 264 {
HannesTschofenig 0:796d0f61a05b 265 return ret;
HannesTschofenig 0:796d0f61a05b 266 }
HannesTschofenig 0:796d0f61a05b 267
HannesTschofenig 0:796d0f61a05b 268 return 0;
HannesTschofenig 0:796d0f61a05b 269 }
HannesTschofenig 0:796d0f61a05b 270
HannesTschofenig 0:796d0f61a05b 271 #if defined(POLARSSL_GCM_C)
HannesTschofenig 0:796d0f61a05b 272 if( ctx->cipher_info->mode == POLARSSL_MODE_GCM )
HannesTschofenig 0:796d0f61a05b 273 {
HannesTschofenig 0:796d0f61a05b 274 *olen = ilen;
HannesTschofenig 0:796d0f61a05b 275 return gcm_update( (gcm_context *) ctx->cipher_ctx, ilen, input,
HannesTschofenig 0:796d0f61a05b 276 output );
HannesTschofenig 0:796d0f61a05b 277 }
HannesTschofenig 0:796d0f61a05b 278 #endif
HannesTschofenig 0:796d0f61a05b 279
HannesTschofenig 0:796d0f61a05b 280 if( input == output &&
HannesTschofenig 0:796d0f61a05b 281 ( ctx->unprocessed_len != 0 || ilen % cipher_get_block_size( ctx ) ) )
HannesTschofenig 0:796d0f61a05b 282 {
HannesTschofenig 0:796d0f61a05b 283 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 284 }
HannesTschofenig 0:796d0f61a05b 285
HannesTschofenig 0:796d0f61a05b 286 #if defined(POLARSSL_CIPHER_MODE_CBC)
HannesTschofenig 0:796d0f61a05b 287 if( ctx->cipher_info->mode == POLARSSL_MODE_CBC )
HannesTschofenig 0:796d0f61a05b 288 {
HannesTschofenig 0:796d0f61a05b 289 size_t copy_len = 0;
HannesTschofenig 0:796d0f61a05b 290
HannesTschofenig 0:796d0f61a05b 291 /*
HannesTschofenig 0:796d0f61a05b 292 * If there is not enough data for a full block, cache it.
HannesTschofenig 0:796d0f61a05b 293 */
HannesTschofenig 0:796d0f61a05b 294 if( ( ctx->operation == POLARSSL_DECRYPT &&
HannesTschofenig 0:796d0f61a05b 295 ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) ||
HannesTschofenig 0:796d0f61a05b 296 ( ctx->operation == POLARSSL_ENCRYPT &&
HannesTschofenig 0:796d0f61a05b 297 ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) )
HannesTschofenig 0:796d0f61a05b 298 {
HannesTschofenig 0:796d0f61a05b 299 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
HannesTschofenig 0:796d0f61a05b 300 ilen );
HannesTschofenig 0:796d0f61a05b 301
HannesTschofenig 0:796d0f61a05b 302 ctx->unprocessed_len += ilen;
HannesTschofenig 0:796d0f61a05b 303 return 0;
HannesTschofenig 0:796d0f61a05b 304 }
HannesTschofenig 0:796d0f61a05b 305
HannesTschofenig 0:796d0f61a05b 306 /*
HannesTschofenig 0:796d0f61a05b 307 * Process cached data first
HannesTschofenig 0:796d0f61a05b 308 */
HannesTschofenig 0:796d0f61a05b 309 if( ctx->unprocessed_len != 0 )
HannesTschofenig 0:796d0f61a05b 310 {
HannesTschofenig 0:796d0f61a05b 311 copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len;
HannesTschofenig 0:796d0f61a05b 312
HannesTschofenig 0:796d0f61a05b 313 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
HannesTschofenig 0:796d0f61a05b 314 copy_len );
HannesTschofenig 0:796d0f61a05b 315
HannesTschofenig 0:796d0f61a05b 316 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
HannesTschofenig 0:796d0f61a05b 317 ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
HannesTschofenig 0:796d0f61a05b 318 ctx->unprocessed_data, output ) ) )
HannesTschofenig 0:796d0f61a05b 319 {
HannesTschofenig 0:796d0f61a05b 320 return ret;
HannesTschofenig 0:796d0f61a05b 321 }
HannesTschofenig 0:796d0f61a05b 322
HannesTschofenig 0:796d0f61a05b 323 *olen += cipher_get_block_size( ctx );
HannesTschofenig 0:796d0f61a05b 324 output += cipher_get_block_size( ctx );
HannesTschofenig 0:796d0f61a05b 325 ctx->unprocessed_len = 0;
HannesTschofenig 0:796d0f61a05b 326
HannesTschofenig 0:796d0f61a05b 327 input += copy_len;
HannesTschofenig 0:796d0f61a05b 328 ilen -= copy_len;
HannesTschofenig 0:796d0f61a05b 329 }
HannesTschofenig 0:796d0f61a05b 330
HannesTschofenig 0:796d0f61a05b 331 /*
HannesTschofenig 0:796d0f61a05b 332 * Cache final, incomplete block
HannesTschofenig 0:796d0f61a05b 333 */
HannesTschofenig 0:796d0f61a05b 334 if( 0 != ilen )
HannesTschofenig 0:796d0f61a05b 335 {
HannesTschofenig 0:796d0f61a05b 336 copy_len = ilen % cipher_get_block_size( ctx );
HannesTschofenig 0:796d0f61a05b 337 if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT )
HannesTschofenig 0:796d0f61a05b 338 copy_len = cipher_get_block_size(ctx);
HannesTschofenig 0:796d0f61a05b 339
HannesTschofenig 0:796d0f61a05b 340 memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
HannesTschofenig 0:796d0f61a05b 341 copy_len );
HannesTschofenig 0:796d0f61a05b 342
HannesTschofenig 0:796d0f61a05b 343 ctx->unprocessed_len += copy_len;
HannesTschofenig 0:796d0f61a05b 344 ilen -= copy_len;
HannesTschofenig 0:796d0f61a05b 345 }
HannesTschofenig 0:796d0f61a05b 346
HannesTschofenig 0:796d0f61a05b 347 /*
HannesTschofenig 0:796d0f61a05b 348 * Process remaining full blocks
HannesTschofenig 0:796d0f61a05b 349 */
HannesTschofenig 0:796d0f61a05b 350 if( ilen )
HannesTschofenig 0:796d0f61a05b 351 {
HannesTschofenig 0:796d0f61a05b 352 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
HannesTschofenig 0:796d0f61a05b 353 ctx->operation, ilen, ctx->iv, input, output ) ) )
HannesTschofenig 0:796d0f61a05b 354 {
HannesTschofenig 0:796d0f61a05b 355 return ret;
HannesTschofenig 0:796d0f61a05b 356 }
HannesTschofenig 0:796d0f61a05b 357
HannesTschofenig 0:796d0f61a05b 358 *olen += ilen;
HannesTschofenig 0:796d0f61a05b 359 }
HannesTschofenig 0:796d0f61a05b 360
HannesTschofenig 0:796d0f61a05b 361 return 0;
HannesTschofenig 0:796d0f61a05b 362 }
HannesTschofenig 0:796d0f61a05b 363 #endif /* POLARSSL_CIPHER_MODE_CBC */
HannesTschofenig 0:796d0f61a05b 364
HannesTschofenig 0:796d0f61a05b 365 #if defined(POLARSSL_CIPHER_MODE_CFB)
HannesTschofenig 0:796d0f61a05b 366 if( ctx->cipher_info->mode == POLARSSL_MODE_CFB )
HannesTschofenig 0:796d0f61a05b 367 {
HannesTschofenig 0:796d0f61a05b 368 if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
HannesTschofenig 0:796d0f61a05b 369 ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
HannesTschofenig 0:796d0f61a05b 370 input, output ) ) )
HannesTschofenig 0:796d0f61a05b 371 {
HannesTschofenig 0:796d0f61a05b 372 return ret;
HannesTschofenig 0:796d0f61a05b 373 }
HannesTschofenig 0:796d0f61a05b 374
HannesTschofenig 0:796d0f61a05b 375 *olen = ilen;
HannesTschofenig 0:796d0f61a05b 376
HannesTschofenig 0:796d0f61a05b 377 return 0;
HannesTschofenig 0:796d0f61a05b 378 }
HannesTschofenig 0:796d0f61a05b 379 #endif /* POLARSSL_CIPHER_MODE_CFB */
HannesTschofenig 0:796d0f61a05b 380
HannesTschofenig 0:796d0f61a05b 381 #if defined(POLARSSL_CIPHER_MODE_CTR)
HannesTschofenig 0:796d0f61a05b 382 if( ctx->cipher_info->mode == POLARSSL_MODE_CTR )
HannesTschofenig 0:796d0f61a05b 383 {
HannesTschofenig 0:796d0f61a05b 384 if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
HannesTschofenig 0:796d0f61a05b 385 ilen, &ctx->unprocessed_len, ctx->iv,
HannesTschofenig 0:796d0f61a05b 386 ctx->unprocessed_data, input, output ) ) )
HannesTschofenig 0:796d0f61a05b 387 {
HannesTschofenig 0:796d0f61a05b 388 return ret;
HannesTschofenig 0:796d0f61a05b 389 }
HannesTschofenig 0:796d0f61a05b 390
HannesTschofenig 0:796d0f61a05b 391 *olen = ilen;
HannesTschofenig 0:796d0f61a05b 392
HannesTschofenig 0:796d0f61a05b 393 return 0;
HannesTschofenig 0:796d0f61a05b 394 }
HannesTschofenig 0:796d0f61a05b 395 #endif /* POLARSSL_CIPHER_MODE_CTR */
HannesTschofenig 0:796d0f61a05b 396
HannesTschofenig 0:796d0f61a05b 397 #if defined(POLARSSL_CIPHER_MODE_STREAM)
HannesTschofenig 0:796d0f61a05b 398 if( ctx->cipher_info->mode == POLARSSL_MODE_STREAM )
HannesTschofenig 0:796d0f61a05b 399 {
HannesTschofenig 0:796d0f61a05b 400 if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
HannesTschofenig 0:796d0f61a05b 401 ilen, input, output ) ) )
HannesTschofenig 0:796d0f61a05b 402 {
HannesTschofenig 0:796d0f61a05b 403 return ret;
HannesTschofenig 0:796d0f61a05b 404 }
HannesTschofenig 0:796d0f61a05b 405
HannesTschofenig 0:796d0f61a05b 406 *olen = ilen;
HannesTschofenig 0:796d0f61a05b 407
HannesTschofenig 0:796d0f61a05b 408 return 0;
HannesTschofenig 0:796d0f61a05b 409 }
HannesTschofenig 0:796d0f61a05b 410 #endif /* POLARSSL_CIPHER_MODE_STREAM */
HannesTschofenig 0:796d0f61a05b 411
HannesTschofenig 0:796d0f61a05b 412 return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
HannesTschofenig 0:796d0f61a05b 413 }
HannesTschofenig 0:796d0f61a05b 414
HannesTschofenig 0:796d0f61a05b 415 #if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
HannesTschofenig 0:796d0f61a05b 416 #if defined(POLARSSL_CIPHER_PADDING_PKCS7)
HannesTschofenig 0:796d0f61a05b 417 /*
HannesTschofenig 0:796d0f61a05b 418 * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
HannesTschofenig 0:796d0f61a05b 419 */
HannesTschofenig 0:796d0f61a05b 420 static void add_pkcs_padding( unsigned char *output, size_t output_len,
HannesTschofenig 0:796d0f61a05b 421 size_t data_len )
HannesTschofenig 0:796d0f61a05b 422 {
HannesTschofenig 0:796d0f61a05b 423 size_t padding_len = output_len - data_len;
HannesTschofenig 0:796d0f61a05b 424 unsigned char i;
HannesTschofenig 0:796d0f61a05b 425
HannesTschofenig 0:796d0f61a05b 426 for( i = 0; i < padding_len; i++ )
HannesTschofenig 0:796d0f61a05b 427 output[data_len + i] = (unsigned char) padding_len;
HannesTschofenig 0:796d0f61a05b 428 }
HannesTschofenig 0:796d0f61a05b 429
HannesTschofenig 0:796d0f61a05b 430 static int get_pkcs_padding( unsigned char *input, size_t input_len,
HannesTschofenig 0:796d0f61a05b 431 size_t *data_len )
HannesTschofenig 0:796d0f61a05b 432 {
HannesTschofenig 0:796d0f61a05b 433 size_t i, pad_idx;
HannesTschofenig 0:796d0f61a05b 434 unsigned char padding_len, bad = 0;
HannesTschofenig 0:796d0f61a05b 435
HannesTschofenig 0:796d0f61a05b 436 if( NULL == input || NULL == data_len )
HannesTschofenig 0:796d0f61a05b 437 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 438
HannesTschofenig 0:796d0f61a05b 439 padding_len = input[input_len - 1];
HannesTschofenig 0:796d0f61a05b 440 *data_len = input_len - padding_len;
HannesTschofenig 0:796d0f61a05b 441
HannesTschofenig 0:796d0f61a05b 442 /* Avoid logical || since it results in a branch */
HannesTschofenig 0:796d0f61a05b 443 bad |= padding_len > input_len;
HannesTschofenig 0:796d0f61a05b 444 bad |= padding_len == 0;
HannesTschofenig 0:796d0f61a05b 445
HannesTschofenig 0:796d0f61a05b 446 /* The number of bytes checked must be independent of padding_len,
HannesTschofenig 0:796d0f61a05b 447 * so pick input_len, which is usually 8 or 16 (one block) */
HannesTschofenig 0:796d0f61a05b 448 pad_idx = input_len - padding_len;
HannesTschofenig 0:796d0f61a05b 449 for( i = 0; i < input_len; i++ )
HannesTschofenig 0:796d0f61a05b 450 bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
HannesTschofenig 0:796d0f61a05b 451
HannesTschofenig 0:796d0f61a05b 452 return POLARSSL_ERR_CIPHER_INVALID_PADDING * (bad != 0);
HannesTschofenig 0:796d0f61a05b 453 }
HannesTschofenig 0:796d0f61a05b 454 #endif /* POLARSSL_CIPHER_PADDING_PKCS7 */
HannesTschofenig 0:796d0f61a05b 455
HannesTschofenig 0:796d0f61a05b 456 #if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS)
HannesTschofenig 0:796d0f61a05b 457 /*
HannesTschofenig 0:796d0f61a05b 458 * One and zeros padding: fill with 80 00 ... 00
HannesTschofenig 0:796d0f61a05b 459 */
HannesTschofenig 0:796d0f61a05b 460 static void add_one_and_zeros_padding( unsigned char *output,
HannesTschofenig 0:796d0f61a05b 461 size_t output_len, size_t data_len )
HannesTschofenig 0:796d0f61a05b 462 {
HannesTschofenig 0:796d0f61a05b 463 size_t padding_len = output_len - data_len;
HannesTschofenig 0:796d0f61a05b 464 unsigned char i = 0;
HannesTschofenig 0:796d0f61a05b 465
HannesTschofenig 0:796d0f61a05b 466 output[data_len] = 0x80;
HannesTschofenig 0:796d0f61a05b 467 for( i = 1; i < padding_len; i++ )
HannesTschofenig 0:796d0f61a05b 468 output[data_len + i] = 0x00;
HannesTschofenig 0:796d0f61a05b 469 }
HannesTschofenig 0:796d0f61a05b 470
HannesTschofenig 0:796d0f61a05b 471 static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
HannesTschofenig 0:796d0f61a05b 472 size_t *data_len )
HannesTschofenig 0:796d0f61a05b 473 {
HannesTschofenig 0:796d0f61a05b 474 size_t i;
HannesTschofenig 0:796d0f61a05b 475 unsigned char done = 0, prev_done, bad;
HannesTschofenig 0:796d0f61a05b 476
HannesTschofenig 0:796d0f61a05b 477 if( NULL == input || NULL == data_len )
HannesTschofenig 0:796d0f61a05b 478 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 479
HannesTschofenig 0:796d0f61a05b 480 bad = 0xFF;
HannesTschofenig 0:796d0f61a05b 481 *data_len = 0;
HannesTschofenig 0:796d0f61a05b 482 for( i = input_len; i > 0; i-- )
HannesTschofenig 0:796d0f61a05b 483 {
HannesTschofenig 0:796d0f61a05b 484 prev_done = done;
HannesTschofenig 0:796d0f61a05b 485 done |= ( input[i-1] != 0 );
HannesTschofenig 0:796d0f61a05b 486 *data_len |= ( i - 1 ) * ( done != prev_done );
HannesTschofenig 0:796d0f61a05b 487 bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done );
HannesTschofenig 0:796d0f61a05b 488 }
HannesTschofenig 0:796d0f61a05b 489
HannesTschofenig 0:796d0f61a05b 490 return POLARSSL_ERR_CIPHER_INVALID_PADDING * (bad != 0);
HannesTschofenig 0:796d0f61a05b 491
HannesTschofenig 0:796d0f61a05b 492 }
HannesTschofenig 0:796d0f61a05b 493 #endif /* POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS */
HannesTschofenig 0:796d0f61a05b 494
HannesTschofenig 0:796d0f61a05b 495 #if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN)
HannesTschofenig 0:796d0f61a05b 496 /*
HannesTschofenig 0:796d0f61a05b 497 * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
HannesTschofenig 0:796d0f61a05b 498 */
HannesTschofenig 0:796d0f61a05b 499 static void add_zeros_and_len_padding( unsigned char *output,
HannesTschofenig 0:796d0f61a05b 500 size_t output_len, size_t data_len )
HannesTschofenig 0:796d0f61a05b 501 {
HannesTschofenig 0:796d0f61a05b 502 size_t padding_len = output_len - data_len;
HannesTschofenig 0:796d0f61a05b 503 unsigned char i = 0;
HannesTschofenig 0:796d0f61a05b 504
HannesTschofenig 0:796d0f61a05b 505 for( i = 1; i < padding_len; i++ )
HannesTschofenig 0:796d0f61a05b 506 output[data_len + i - 1] = 0x00;
HannesTschofenig 0:796d0f61a05b 507 output[output_len - 1] = (unsigned char) padding_len;
HannesTschofenig 0:796d0f61a05b 508 }
HannesTschofenig 0:796d0f61a05b 509
HannesTschofenig 0:796d0f61a05b 510 static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
HannesTschofenig 0:796d0f61a05b 511 size_t *data_len )
HannesTschofenig 0:796d0f61a05b 512 {
HannesTschofenig 0:796d0f61a05b 513 size_t i, pad_idx;
HannesTschofenig 0:796d0f61a05b 514 unsigned char padding_len, bad = 0;
HannesTschofenig 0:796d0f61a05b 515
HannesTschofenig 0:796d0f61a05b 516 if( NULL == input || NULL == data_len )
HannesTschofenig 0:796d0f61a05b 517 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 518
HannesTschofenig 0:796d0f61a05b 519 padding_len = input[input_len - 1];
HannesTschofenig 0:796d0f61a05b 520 *data_len = input_len - padding_len;
HannesTschofenig 0:796d0f61a05b 521
HannesTschofenig 0:796d0f61a05b 522 /* Avoid logical || since it results in a branch */
HannesTschofenig 0:796d0f61a05b 523 bad |= padding_len > input_len;
HannesTschofenig 0:796d0f61a05b 524 bad |= padding_len == 0;
HannesTschofenig 0:796d0f61a05b 525
HannesTschofenig 0:796d0f61a05b 526 /* The number of bytes checked must be independent of padding_len */
HannesTschofenig 0:796d0f61a05b 527 pad_idx = input_len - padding_len;
HannesTschofenig 0:796d0f61a05b 528 for( i = 0; i < input_len - 1; i++ )
HannesTschofenig 0:796d0f61a05b 529 bad |= input[i] * ( i >= pad_idx );
HannesTschofenig 0:796d0f61a05b 530
HannesTschofenig 0:796d0f61a05b 531 return POLARSSL_ERR_CIPHER_INVALID_PADDING * (bad != 0);
HannesTschofenig 0:796d0f61a05b 532 }
HannesTschofenig 0:796d0f61a05b 533 #endif /* POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN */
HannesTschofenig 0:796d0f61a05b 534
HannesTschofenig 0:796d0f61a05b 535 #if defined(POLARSSL_CIPHER_PADDING_ZEROS)
HannesTschofenig 0:796d0f61a05b 536 /*
HannesTschofenig 0:796d0f61a05b 537 * Zero padding: fill with 00 ... 00
HannesTschofenig 0:796d0f61a05b 538 */
HannesTschofenig 0:796d0f61a05b 539 static void add_zeros_padding( unsigned char *output,
HannesTschofenig 0:796d0f61a05b 540 size_t output_len, size_t data_len )
HannesTschofenig 0:796d0f61a05b 541 {
HannesTschofenig 0:796d0f61a05b 542 size_t i;
HannesTschofenig 0:796d0f61a05b 543
HannesTschofenig 0:796d0f61a05b 544 for( i = data_len; i < output_len; i++ )
HannesTschofenig 0:796d0f61a05b 545 output[i] = 0x00;
HannesTschofenig 0:796d0f61a05b 546 }
HannesTschofenig 0:796d0f61a05b 547
HannesTschofenig 0:796d0f61a05b 548 static int get_zeros_padding( unsigned char *input, size_t input_len,
HannesTschofenig 0:796d0f61a05b 549 size_t *data_len )
HannesTschofenig 0:796d0f61a05b 550 {
HannesTschofenig 0:796d0f61a05b 551 size_t i;
HannesTschofenig 0:796d0f61a05b 552 unsigned char done = 0, prev_done;
HannesTschofenig 0:796d0f61a05b 553
HannesTschofenig 0:796d0f61a05b 554 if( NULL == input || NULL == data_len )
HannesTschofenig 0:796d0f61a05b 555 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 556
HannesTschofenig 0:796d0f61a05b 557 *data_len = 0;
HannesTschofenig 0:796d0f61a05b 558 for( i = input_len; i > 0; i-- )
HannesTschofenig 0:796d0f61a05b 559 {
HannesTschofenig 0:796d0f61a05b 560 prev_done = done;
HannesTschofenig 0:796d0f61a05b 561 done |= ( input[i-1] != 0 );
HannesTschofenig 0:796d0f61a05b 562 *data_len |= i * ( done != prev_done );
HannesTschofenig 0:796d0f61a05b 563 }
HannesTschofenig 0:796d0f61a05b 564
HannesTschofenig 0:796d0f61a05b 565 return 0;
HannesTschofenig 0:796d0f61a05b 566 }
HannesTschofenig 0:796d0f61a05b 567 #endif /* POLARSSL_CIPHER_PADDING_ZEROS */
HannesTschofenig 0:796d0f61a05b 568
HannesTschofenig 0:796d0f61a05b 569 /*
HannesTschofenig 0:796d0f61a05b 570 * No padding: don't pad :)
HannesTschofenig 0:796d0f61a05b 571 *
HannesTschofenig 0:796d0f61a05b 572 * There is no add_padding function (check for NULL in cipher_finish)
HannesTschofenig 0:796d0f61a05b 573 * but a trivial get_padding function
HannesTschofenig 0:796d0f61a05b 574 */
HannesTschofenig 0:796d0f61a05b 575 static int get_no_padding( unsigned char *input, size_t input_len,
HannesTschofenig 0:796d0f61a05b 576 size_t *data_len )
HannesTschofenig 0:796d0f61a05b 577 {
HannesTschofenig 0:796d0f61a05b 578 if( NULL == input || NULL == data_len )
HannesTschofenig 0:796d0f61a05b 579 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 580
HannesTschofenig 0:796d0f61a05b 581 *data_len = input_len;
HannesTschofenig 0:796d0f61a05b 582
HannesTschofenig 0:796d0f61a05b 583 return 0;
HannesTschofenig 0:796d0f61a05b 584 }
HannesTschofenig 0:796d0f61a05b 585 #endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
HannesTschofenig 0:796d0f61a05b 586
HannesTschofenig 0:796d0f61a05b 587 int cipher_finish( cipher_context_t *ctx,
HannesTschofenig 0:796d0f61a05b 588 unsigned char *output, size_t *olen )
HannesTschofenig 0:796d0f61a05b 589 {
HannesTschofenig 0:796d0f61a05b 590 if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
HannesTschofenig 0:796d0f61a05b 591 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 592
HannesTschofenig 0:796d0f61a05b 593 *olen = 0;
HannesTschofenig 0:796d0f61a05b 594
HannesTschofenig 0:796d0f61a05b 595 if( POLARSSL_MODE_CFB == ctx->cipher_info->mode ||
HannesTschofenig 0:796d0f61a05b 596 POLARSSL_MODE_CTR == ctx->cipher_info->mode ||
HannesTschofenig 0:796d0f61a05b 597 POLARSSL_MODE_GCM == ctx->cipher_info->mode ||
HannesTschofenig 0:796d0f61a05b 598 POLARSSL_MODE_STREAM == ctx->cipher_info->mode )
HannesTschofenig 0:796d0f61a05b 599 {
HannesTschofenig 0:796d0f61a05b 600 return 0;
HannesTschofenig 0:796d0f61a05b 601 }
HannesTschofenig 0:796d0f61a05b 602
HannesTschofenig 0:796d0f61a05b 603 if( POLARSSL_MODE_ECB == ctx->cipher_info->mode )
HannesTschofenig 0:796d0f61a05b 604 {
HannesTschofenig 0:796d0f61a05b 605 if( ctx->unprocessed_len != 0 )
HannesTschofenig 0:796d0f61a05b 606 return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
HannesTschofenig 0:796d0f61a05b 607
HannesTschofenig 0:796d0f61a05b 608 return 0;
HannesTschofenig 0:796d0f61a05b 609 }
HannesTschofenig 0:796d0f61a05b 610
HannesTschofenig 0:796d0f61a05b 611 #if defined(POLARSSL_CIPHER_MODE_CBC)
HannesTschofenig 0:796d0f61a05b 612 if( POLARSSL_MODE_CBC == ctx->cipher_info->mode )
HannesTschofenig 0:796d0f61a05b 613 {
HannesTschofenig 0:796d0f61a05b 614 int ret = 0;
HannesTschofenig 0:796d0f61a05b 615
HannesTschofenig 0:796d0f61a05b 616 if( POLARSSL_ENCRYPT == ctx->operation )
HannesTschofenig 0:796d0f61a05b 617 {
HannesTschofenig 0:796d0f61a05b 618 /* check for 'no padding' mode */
HannesTschofenig 0:796d0f61a05b 619 if( NULL == ctx->add_padding )
HannesTschofenig 0:796d0f61a05b 620 {
HannesTschofenig 0:796d0f61a05b 621 if( 0 != ctx->unprocessed_len )
HannesTschofenig 0:796d0f61a05b 622 return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
HannesTschofenig 0:796d0f61a05b 623
HannesTschofenig 0:796d0f61a05b 624 return 0;
HannesTschofenig 0:796d0f61a05b 625 }
HannesTschofenig 0:796d0f61a05b 626
HannesTschofenig 0:796d0f61a05b 627 ctx->add_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ),
HannesTschofenig 0:796d0f61a05b 628 ctx->unprocessed_len );
HannesTschofenig 0:796d0f61a05b 629 }
HannesTschofenig 0:796d0f61a05b 630 else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len )
HannesTschofenig 0:796d0f61a05b 631 {
HannesTschofenig 0:796d0f61a05b 632 /*
HannesTschofenig 0:796d0f61a05b 633 * For decrypt operations, expect a full block,
HannesTschofenig 0:796d0f61a05b 634 * or an empty block if no padding
HannesTschofenig 0:796d0f61a05b 635 */
HannesTschofenig 0:796d0f61a05b 636 if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
HannesTschofenig 0:796d0f61a05b 637 return 0;
HannesTschofenig 0:796d0f61a05b 638
HannesTschofenig 0:796d0f61a05b 639 return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
HannesTschofenig 0:796d0f61a05b 640 }
HannesTschofenig 0:796d0f61a05b 641
HannesTschofenig 0:796d0f61a05b 642 /* cipher block */
HannesTschofenig 0:796d0f61a05b 643 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
HannesTschofenig 0:796d0f61a05b 644 ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
HannesTschofenig 0:796d0f61a05b 645 ctx->unprocessed_data, output ) ) )
HannesTschofenig 0:796d0f61a05b 646 {
HannesTschofenig 0:796d0f61a05b 647 return ret;
HannesTschofenig 0:796d0f61a05b 648 }
HannesTschofenig 0:796d0f61a05b 649
HannesTschofenig 0:796d0f61a05b 650 /* Set output size for decryption */
HannesTschofenig 0:796d0f61a05b 651 if( POLARSSL_DECRYPT == ctx->operation )
HannesTschofenig 0:796d0f61a05b 652 return ctx->get_padding( output, cipher_get_block_size( ctx ),
HannesTschofenig 0:796d0f61a05b 653 olen );
HannesTschofenig 0:796d0f61a05b 654
HannesTschofenig 0:796d0f61a05b 655 /* Set output size for encryption */
HannesTschofenig 0:796d0f61a05b 656 *olen = cipher_get_block_size( ctx );
HannesTschofenig 0:796d0f61a05b 657 return 0;
HannesTschofenig 0:796d0f61a05b 658 }
HannesTschofenig 0:796d0f61a05b 659 #else
HannesTschofenig 0:796d0f61a05b 660 ((void) output);
HannesTschofenig 0:796d0f61a05b 661 #endif /* POLARSSL_CIPHER_MODE_CBC */
HannesTschofenig 0:796d0f61a05b 662
HannesTschofenig 0:796d0f61a05b 663 return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
HannesTschofenig 0:796d0f61a05b 664 }
HannesTschofenig 0:796d0f61a05b 665
HannesTschofenig 0:796d0f61a05b 666 #if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
HannesTschofenig 0:796d0f61a05b 667 int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode )
HannesTschofenig 0:796d0f61a05b 668 {
HannesTschofenig 0:796d0f61a05b 669 if( NULL == ctx ||
HannesTschofenig 0:796d0f61a05b 670 POLARSSL_MODE_CBC != ctx->cipher_info->mode )
HannesTschofenig 0:796d0f61a05b 671 {
HannesTschofenig 0:796d0f61a05b 672 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 673 }
HannesTschofenig 0:796d0f61a05b 674
HannesTschofenig 0:796d0f61a05b 675 switch( mode )
HannesTschofenig 0:796d0f61a05b 676 {
HannesTschofenig 0:796d0f61a05b 677 #if defined(POLARSSL_CIPHER_PADDING_PKCS7)
HannesTschofenig 0:796d0f61a05b 678 case POLARSSL_PADDING_PKCS7:
HannesTschofenig 0:796d0f61a05b 679 ctx->add_padding = add_pkcs_padding;
HannesTschofenig 0:796d0f61a05b 680 ctx->get_padding = get_pkcs_padding;
HannesTschofenig 0:796d0f61a05b 681 break;
HannesTschofenig 0:796d0f61a05b 682 #endif
HannesTschofenig 0:796d0f61a05b 683 #if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS)
HannesTschofenig 0:796d0f61a05b 684 case POLARSSL_PADDING_ONE_AND_ZEROS:
HannesTschofenig 0:796d0f61a05b 685 ctx->add_padding = add_one_and_zeros_padding;
HannesTschofenig 0:796d0f61a05b 686 ctx->get_padding = get_one_and_zeros_padding;
HannesTschofenig 0:796d0f61a05b 687 break;
HannesTschofenig 0:796d0f61a05b 688 #endif
HannesTschofenig 0:796d0f61a05b 689 #if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN)
HannesTschofenig 0:796d0f61a05b 690 case POLARSSL_PADDING_ZEROS_AND_LEN:
HannesTschofenig 0:796d0f61a05b 691 ctx->add_padding = add_zeros_and_len_padding;
HannesTschofenig 0:796d0f61a05b 692 ctx->get_padding = get_zeros_and_len_padding;
HannesTschofenig 0:796d0f61a05b 693 break;
HannesTschofenig 0:796d0f61a05b 694 #endif
HannesTschofenig 0:796d0f61a05b 695 #if defined(POLARSSL_CIPHER_PADDING_ZEROS)
HannesTschofenig 0:796d0f61a05b 696 case POLARSSL_PADDING_ZEROS:
HannesTschofenig 0:796d0f61a05b 697 ctx->add_padding = add_zeros_padding;
HannesTschofenig 0:796d0f61a05b 698 ctx->get_padding = get_zeros_padding;
HannesTschofenig 0:796d0f61a05b 699 break;
HannesTschofenig 0:796d0f61a05b 700 #endif
HannesTschofenig 0:796d0f61a05b 701 case POLARSSL_PADDING_NONE:
HannesTschofenig 0:796d0f61a05b 702 ctx->add_padding = NULL;
HannesTschofenig 0:796d0f61a05b 703 ctx->get_padding = get_no_padding;
HannesTschofenig 0:796d0f61a05b 704 break;
HannesTschofenig 0:796d0f61a05b 705
HannesTschofenig 0:796d0f61a05b 706 default:
HannesTschofenig 0:796d0f61a05b 707 return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
HannesTschofenig 0:796d0f61a05b 708 }
HannesTschofenig 0:796d0f61a05b 709
HannesTschofenig 0:796d0f61a05b 710 return 0;
HannesTschofenig 0:796d0f61a05b 711 }
HannesTschofenig 0:796d0f61a05b 712 #endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
HannesTschofenig 0:796d0f61a05b 713
HannesTschofenig 0:796d0f61a05b 714 #if defined(POLARSSL_CIPHER_MODE_AEAD)
HannesTschofenig 0:796d0f61a05b 715 int cipher_write_tag( cipher_context_t *ctx,
HannesTschofenig 0:796d0f61a05b 716 unsigned char *tag, size_t tag_len )
HannesTschofenig 0:796d0f61a05b 717 {
HannesTschofenig 0:796d0f61a05b 718 if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
HannesTschofenig 0:796d0f61a05b 719 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 720
HannesTschofenig 0:796d0f61a05b 721 if( POLARSSL_ENCRYPT != ctx->operation )
HannesTschofenig 0:796d0f61a05b 722 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 723
HannesTschofenig 0:796d0f61a05b 724 #if defined(POLARSSL_GCM_C)
HannesTschofenig 0:796d0f61a05b 725 if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
HannesTschofenig 0:796d0f61a05b 726 return gcm_finish( (gcm_context *) ctx->cipher_ctx, tag, tag_len );
HannesTschofenig 0:796d0f61a05b 727 #endif
HannesTschofenig 0:796d0f61a05b 728
HannesTschofenig 0:796d0f61a05b 729 return 0;
HannesTschofenig 0:796d0f61a05b 730 }
HannesTschofenig 0:796d0f61a05b 731
HannesTschofenig 0:796d0f61a05b 732 int cipher_check_tag( cipher_context_t *ctx,
HannesTschofenig 0:796d0f61a05b 733 const unsigned char *tag, size_t tag_len )
HannesTschofenig 0:796d0f61a05b 734 {
HannesTschofenig 0:796d0f61a05b 735 int ret;
HannesTschofenig 0:796d0f61a05b 736
HannesTschofenig 0:796d0f61a05b 737 if( NULL == ctx || NULL == ctx->cipher_info ||
HannesTschofenig 0:796d0f61a05b 738 POLARSSL_DECRYPT != ctx->operation )
HannesTschofenig 0:796d0f61a05b 739 {
HannesTschofenig 0:796d0f61a05b 740 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 741 }
HannesTschofenig 0:796d0f61a05b 742
HannesTschofenig 0:796d0f61a05b 743 #if defined(POLARSSL_GCM_C)
HannesTschofenig 0:796d0f61a05b 744 if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
HannesTschofenig 0:796d0f61a05b 745 {
HannesTschofenig 0:796d0f61a05b 746 unsigned char check_tag[16];
HannesTschofenig 0:796d0f61a05b 747 size_t i;
HannesTschofenig 0:796d0f61a05b 748 int diff;
HannesTschofenig 0:796d0f61a05b 749
HannesTschofenig 0:796d0f61a05b 750 if( tag_len > sizeof( check_tag ) )
HannesTschofenig 0:796d0f61a05b 751 return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
HannesTschofenig 0:796d0f61a05b 752
HannesTschofenig 0:796d0f61a05b 753 if( 0 != ( ret = gcm_finish( (gcm_context *) ctx->cipher_ctx,
HannesTschofenig 0:796d0f61a05b 754 check_tag, tag_len ) ) )
HannesTschofenig 0:796d0f61a05b 755 {
HannesTschofenig 0:796d0f61a05b 756 return( ret );
HannesTschofenig 0:796d0f61a05b 757 }
HannesTschofenig 0:796d0f61a05b 758
HannesTschofenig 0:796d0f61a05b 759 /* Check the tag in "constant-time" */
HannesTschofenig 0:796d0f61a05b 760 for( diff = 0, i = 0; i < tag_len; i++ )
HannesTschofenig 0:796d0f61a05b 761 diff |= tag[i] ^ check_tag[i];
HannesTschofenig 0:796d0f61a05b 762
HannesTschofenig 0:796d0f61a05b 763 if( diff != 0 )
HannesTschofenig 0:796d0f61a05b 764 return( POLARSSL_ERR_CIPHER_AUTH_FAILED );
HannesTschofenig 0:796d0f61a05b 765
HannesTschofenig 0:796d0f61a05b 766 return( 0 );
HannesTschofenig 0:796d0f61a05b 767 }
HannesTschofenig 0:796d0f61a05b 768 #endif /* POLARSSL_GCM_C */
HannesTschofenig 0:796d0f61a05b 769
HannesTschofenig 0:796d0f61a05b 770 return( 0 );
HannesTschofenig 0:796d0f61a05b 771 }
HannesTschofenig 0:796d0f61a05b 772 #endif /* POLARSSL_CIPHER_MODE_AEAD */
HannesTschofenig 0:796d0f61a05b 773
HannesTschofenig 0:796d0f61a05b 774 #if defined(POLARSSL_SELF_TEST)
HannesTschofenig 0:796d0f61a05b 775
HannesTschofenig 0:796d0f61a05b 776 /*
HannesTschofenig 0:796d0f61a05b 777 * Checkup routine
HannesTschofenig 0:796d0f61a05b 778 */
HannesTschofenig 0:796d0f61a05b 779 int cipher_self_test( int verbose )
HannesTschofenig 0:796d0f61a05b 780 {
HannesTschofenig 0:796d0f61a05b 781 ((void) verbose);
HannesTschofenig 0:796d0f61a05b 782
HannesTschofenig 0:796d0f61a05b 783 return( 0 );
HannesTschofenig 0:796d0f61a05b 784 }
HannesTschofenig 0:796d0f61a05b 785
HannesTschofenig 0:796d0f61a05b 786 #endif /* POLARSSL_SELF_TEST */
HannesTschofenig 0:796d0f61a05b 787
HannesTschofenig 0:796d0f61a05b 788 #endif /* POLARSSL_CIPHER_C */
HannesTschofenig 0:796d0f61a05b 789
HannesTschofenig 0:796d0f61a05b 790