|  | @@ -1,17 +1,65 @@
 | 
		
	
		
			
			| 1 |  | -#include "crypto/axtls/crypto.h"
 | 
		
	
		
			
			|  | 1 | +/*
 | 
		
	
		
			
			|  | 2 | + * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
 | 
		
	
		
			
			|  | 3 | + *
 | 
		
	
		
			
			|  | 4 | + * This program is free software; you can redistribute it and/or
 | 
		
	
		
			
			|  | 5 | + * modify it under the terms of the GNU General Public License as
 | 
		
	
		
			
			|  | 6 | + * published by the Free Software Foundation; either version 2 of the
 | 
		
	
		
			
			|  | 7 | + * License, or any later version.
 | 
		
	
		
			
			|  | 8 | + *
 | 
		
	
		
			
			|  | 9 | + * This program is distributed in the hope that it will be useful, but
 | 
		
	
		
			
			|  | 10 | + * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
		
	
		
			
			|  | 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
		
	
		
			
			|  | 12 | + * General Public License for more details.
 | 
		
	
		
			
			|  | 13 | + *
 | 
		
	
		
			
			|  | 14 | + * You should have received a copy of the GNU General Public License
 | 
		
	
		
			
			|  | 15 | + * along with this program; if not, write to the Free Software
 | 
		
	
		
			
			|  | 16 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
		
	
		
			
			|  | 17 | + */
 | 
		
	
		
			
			|  | 18 | +
 | 
		
	
		
			
			| 2 | 19 |  #include <string.h>
 | 
		
	
		
			
			| 3 | 20 |  #include <errno.h>
 | 
		
	
		
			
			|  | 21 | +#include <byteswap.h>
 | 
		
	
		
			
			| 4 | 22 |  #include <gpxe/crypto.h>
 | 
		
	
		
			
			|  | 23 | +#include <gpxe/cbc.h>
 | 
		
	
		
			
			| 5 | 24 |  #include <gpxe/aes.h>
 | 
		
	
		
			
			|  | 25 | +#include "crypto/axtls/crypto.h"
 | 
		
	
		
			
			| 6 | 26 |  
 | 
		
	
		
			
			| 7 |  | -struct aes_cbc_context {
 | 
		
	
		
			
			| 8 |  | -	AES_CTX ctx;
 | 
		
	
		
			
			|  | 27 | +/** @file
 | 
		
	
		
			
			|  | 28 | + *
 | 
		
	
		
			
			|  | 29 | + * AES algorithm
 | 
		
	
		
			
			|  | 30 | + *
 | 
		
	
		
			
			|  | 31 | + */
 | 
		
	
		
			
			|  | 32 | +
 | 
		
	
		
			
			|  | 33 | +/** Basic AES blocksize */
 | 
		
	
		
			
			|  | 34 | +#define AES_BLOCKSIZE 16
 | 
		
	
		
			
			|  | 35 | +
 | 
		
	
		
			
			|  | 36 | +/****************************************************************************
 | 
		
	
		
			
			|  | 37 | + *
 | 
		
	
		
			
			|  | 38 | + * Basic AES algorithm (independent of mode of operation)
 | 
		
	
		
			
			|  | 39 | + *
 | 
		
	
		
			
			|  | 40 | + ****************************************************************************
 | 
		
	
		
			
			|  | 41 | + */
 | 
		
	
		
			
			|  | 42 | +
 | 
		
	
		
			
			|  | 43 | +/** AES context */
 | 
		
	
		
			
			|  | 44 | +struct aes_context {
 | 
		
	
		
			
			|  | 45 | +	/** AES context for AXTLS */
 | 
		
	
		
			
			|  | 46 | +	AES_CTX axtls_ctx;
 | 
		
	
		
			
			|  | 47 | +	/** Cipher is being used for decrypting */
 | 
		
	
		
			
			| 9 | 48 |  	int decrypting;
 | 
		
	
		
			
			| 10 | 49 |  };
 | 
		
	
		
			
			| 11 | 50 |  
 | 
		
	
		
			
			| 12 |  | -static int aes_cbc_setkey ( void *ctx, const void *key, size_t keylen ) {
 | 
		
	
		
			
			| 13 |  | -	struct aes_cbc_context *aesctx = ctx;
 | 
		
	
		
			
			|  | 51 | +/**
 | 
		
	
		
			
			|  | 52 | + * Set key
 | 
		
	
		
			
			|  | 53 | + *
 | 
		
	
		
			
			|  | 54 | + * @v ctx		Context
 | 
		
	
		
			
			|  | 55 | + * @v key		Key
 | 
		
	
		
			
			|  | 56 | + * @v keylen		Key length
 | 
		
	
		
			
			|  | 57 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 58 | + */
 | 
		
	
		
			
			|  | 59 | +static int aes_setkey ( void *ctx, const void *key, size_t keylen ) {
 | 
		
	
		
			
			|  | 60 | +	struct aes_context *aes_ctx = ctx;
 | 
		
	
		
			
			| 14 | 61 |  	AES_MODE mode;
 | 
		
	
		
			
			|  | 62 | +	void *iv;
 | 
		
	
		
			
			| 15 | 63 |  
 | 
		
	
		
			
			| 16 | 64 |  	switch ( keylen ) {
 | 
		
	
		
			
			| 17 | 65 |  	case ( 128 / 8 ):
 | 
		
	
	
		
			
			|  | @@ -24,45 +72,182 @@ static int aes_cbc_setkey ( void *ctx, const void *key, size_t keylen ) {
 | 
		
	
		
			
			| 24 | 72 |  		return -EINVAL;
 | 
		
	
		
			
			| 25 | 73 |  	}
 | 
		
	
		
			
			| 26 | 74 |  
 | 
		
	
		
			
			| 27 |  | -	AES_set_key ( &aesctx->ctx, key, aesctx->ctx.iv, mode );
 | 
		
	
		
			
			|  | 75 | +	/* IV is not a relevant concept at this stage; use a dummy
 | 
		
	
		
			
			|  | 76 | +	 * value that will have no side-effects.
 | 
		
	
		
			
			|  | 77 | +	 */
 | 
		
	
		
			
			|  | 78 | +	iv = &aes_ctx->axtls_ctx.iv;
 | 
		
	
		
			
			|  | 79 | +
 | 
		
	
		
			
			|  | 80 | +	AES_set_key ( &aes_ctx->axtls_ctx, key, iv, mode );
 | 
		
	
		
			
			| 28 | 81 |  
 | 
		
	
		
			
			| 29 |  | -	aesctx->decrypting = 0;
 | 
		
	
		
			
			|  | 82 | +	aes_ctx->decrypting = 0;
 | 
		
	
		
			
			| 30 | 83 |  
 | 
		
	
		
			
			| 31 | 84 |  	return 0;
 | 
		
	
		
			
			| 32 | 85 |  }
 | 
		
	
		
			
			| 33 | 86 |  
 | 
		
	
		
			
			| 34 |  | -static void aes_cbc_setiv ( void *ctx, const void *iv ) {
 | 
		
	
		
			
			| 35 |  | -	struct aes_cbc_context *aesctx = ctx;
 | 
		
	
		
			
			|  | 87 | +/**
 | 
		
	
		
			
			|  | 88 | + * Set initialisation vector
 | 
		
	
		
			
			|  | 89 | + *
 | 
		
	
		
			
			|  | 90 | + * @v ctx		Context
 | 
		
	
		
			
			|  | 91 | + * @v iv		Initialisation vector
 | 
		
	
		
			
			|  | 92 | + */
 | 
		
	
		
			
			|  | 93 | +static void aes_setiv ( void *ctx __unused, const void *iv __unused ) {
 | 
		
	
		
			
			|  | 94 | +	/* Nothing to do */
 | 
		
	
		
			
			|  | 95 | +}
 | 
		
	
		
			
			| 36 | 96 |  
 | 
		
	
		
			
			| 37 |  | -	memcpy ( aesctx->ctx.iv, iv, sizeof ( aesctx->ctx.iv ) );
 | 
		
	
		
			
			|  | 97 | +/**
 | 
		
	
		
			
			|  | 98 | + * Call AXTLS' AES_encrypt() or AES_decrypt() functions
 | 
		
	
		
			
			|  | 99 | + *
 | 
		
	
		
			
			|  | 100 | + * @v axtls_ctx		AXTLS AES context
 | 
		
	
		
			
			|  | 101 | + * @v src		Data to process
 | 
		
	
		
			
			|  | 102 | + * @v dst		Buffer for output
 | 
		
	
		
			
			|  | 103 | + * @v func		AXTLS AES function to call
 | 
		
	
		
			
			|  | 104 | + */
 | 
		
	
		
			
			|  | 105 | +static void aes_call_axtls ( AES_CTX *axtls_ctx, const void *src, void *dst,
 | 
		
	
		
			
			|  | 106 | +			     void ( * func ) ( const AES_CTX *axtls_ctx,
 | 
		
	
		
			
			|  | 107 | +					       uint32_t *data ) ){
 | 
		
	
		
			
			|  | 108 | +	const uint32_t *srcl = src;
 | 
		
	
		
			
			|  | 109 | +	uint32_t *dstl = dst;
 | 
		
	
		
			
			|  | 110 | +	unsigned int i;
 | 
		
	
		
			
			|  | 111 | +
 | 
		
	
		
			
			|  | 112 | +	/* AXTLS' AES_encrypt() and AES_decrypt() functions both
 | 
		
	
		
			
			|  | 113 | +	 * expect to deal with an array of four dwords in host-endian
 | 
		
	
		
			
			|  | 114 | +	 * order.
 | 
		
	
		
			
			|  | 115 | +	 */
 | 
		
	
		
			
			|  | 116 | +	for ( i = 0 ; i < 4 ; i++ )
 | 
		
	
		
			
			|  | 117 | +		dstl[i] = ntohl ( srcl[i] );
 | 
		
	
		
			
			|  | 118 | +	func ( axtls_ctx, dstl );
 | 
		
	
		
			
			|  | 119 | +	for ( i = 0 ; i < 4 ; i++ )
 | 
		
	
		
			
			|  | 120 | +		dstl[i] = htonl ( dstl[i] );
 | 
		
	
		
			
			| 38 | 121 |  }
 | 
		
	
		
			
			| 39 | 122 |  
 | 
		
	
		
			
			| 40 |  | -static void aes_cbc_encrypt ( void *ctx, const void *data, void *dst,
 | 
		
	
		
			
			| 41 |  | -			      size_t len ) {
 | 
		
	
		
			
			| 42 |  | -	struct aes_cbc_context *aesctx = ctx;
 | 
		
	
		
			
			|  | 123 | +/**
 | 
		
	
		
			
			|  | 124 | + * Encrypt data
 | 
		
	
		
			
			|  | 125 | + *
 | 
		
	
		
			
			|  | 126 | + * @v ctx		Context
 | 
		
	
		
			
			|  | 127 | + * @v src		Data to encrypt
 | 
		
	
		
			
			|  | 128 | + * @v dst		Buffer for encrypted data
 | 
		
	
		
			
			|  | 129 | + * @v len		Length of data
 | 
		
	
		
			
			|  | 130 | + */
 | 
		
	
		
			
			|  | 131 | +static void aes_encrypt ( void *ctx, const void *src, void *dst,
 | 
		
	
		
			
			|  | 132 | +			  size_t len ) {
 | 
		
	
		
			
			|  | 133 | +	struct aes_context *aes_ctx = ctx;
 | 
		
	
		
			
			| 43 | 134 |  
 | 
		
	
		
			
			| 44 |  | -	if ( aesctx->decrypting )
 | 
		
	
		
			
			|  | 135 | +	assert ( len == AES_BLOCKSIZE );
 | 
		
	
		
			
			|  | 136 | +	if ( aes_ctx->decrypting )
 | 
		
	
		
			
			| 45 | 137 |  		assert ( 0 );
 | 
		
	
		
			
			|  | 138 | +	aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_encrypt );
 | 
		
	
		
			
			|  | 139 | +}
 | 
		
	
		
			
			|  | 140 | +
 | 
		
	
		
			
			|  | 141 | +/**
 | 
		
	
		
			
			|  | 142 | + * Decrypt data
 | 
		
	
		
			
			|  | 143 | + *
 | 
		
	
		
			
			|  | 144 | + * @v ctx		Context
 | 
		
	
		
			
			|  | 145 | + * @v src		Data to decrypt
 | 
		
	
		
			
			|  | 146 | + * @v dst		Buffer for decrypted data
 | 
		
	
		
			
			|  | 147 | + * @v len		Length of data
 | 
		
	
		
			
			|  | 148 | + */
 | 
		
	
		
			
			|  | 149 | +static void aes_decrypt ( void *ctx, const void *src, void *dst,
 | 
		
	
		
			
			|  | 150 | +			  size_t len ) {
 | 
		
	
		
			
			|  | 151 | +	struct aes_context *aes_ctx = ctx;
 | 
		
	
		
			
			|  | 152 | +
 | 
		
	
		
			
			|  | 153 | +	assert ( len == AES_BLOCKSIZE );
 | 
		
	
		
			
			|  | 154 | +	if ( ! aes_ctx->decrypting ) {
 | 
		
	
		
			
			|  | 155 | +		AES_convert_key ( &aes_ctx->axtls_ctx );
 | 
		
	
		
			
			|  | 156 | +		aes_ctx->decrypting = 1;
 | 
		
	
		
			
			|  | 157 | +	}
 | 
		
	
		
			
			|  | 158 | +	aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_decrypt );
 | 
		
	
		
			
			|  | 159 | +}
 | 
		
	
		
			
			|  | 160 | +
 | 
		
	
		
			
			|  | 161 | +/** Basic AES algorithm */
 | 
		
	
		
			
			|  | 162 | +static struct cipher_algorithm aes_algorithm = {
 | 
		
	
		
			
			|  | 163 | +	.name = "aes",
 | 
		
	
		
			
			|  | 164 | +	.ctxsize = sizeof ( struct aes_context ),
 | 
		
	
		
			
			|  | 165 | +	.blocksize = AES_BLOCKSIZE,
 | 
		
	
		
			
			|  | 166 | +	.setkey = aes_setkey,
 | 
		
	
		
			
			|  | 167 | +	.setiv = aes_setiv,
 | 
		
	
		
			
			|  | 168 | +	.encrypt = aes_encrypt,
 | 
		
	
		
			
			|  | 169 | +	.decrypt = aes_decrypt,
 | 
		
	
		
			
			|  | 170 | +};
 | 
		
	
		
			
			|  | 171 | +
 | 
		
	
		
			
			|  | 172 | +/****************************************************************************
 | 
		
	
		
			
			|  | 173 | + *
 | 
		
	
		
			
			|  | 174 | + * AES with cipher-block chaining (CBC)
 | 
		
	
		
			
			|  | 175 | + *
 | 
		
	
		
			
			|  | 176 | + ****************************************************************************
 | 
		
	
		
			
			|  | 177 | + */
 | 
		
	
		
			
			|  | 178 | +
 | 
		
	
		
			
			|  | 179 | +/** AES with CBC context */
 | 
		
	
		
			
			|  | 180 | +struct aes_cbc_context {
 | 
		
	
		
			
			|  | 181 | +	/** AES context */
 | 
		
	
		
			
			|  | 182 | +	struct aes_context aes_ctx;
 | 
		
	
		
			
			|  | 183 | +	/** CBC context */
 | 
		
	
		
			
			|  | 184 | +	uint8_t cbc_ctx[AES_BLOCKSIZE];
 | 
		
	
		
			
			|  | 185 | +};
 | 
		
	
		
			
			|  | 186 | +
 | 
		
	
		
			
			|  | 187 | +/**
 | 
		
	
		
			
			|  | 188 | + * Set key
 | 
		
	
		
			
			|  | 189 | + *
 | 
		
	
		
			
			|  | 190 | + * @v ctx		Context
 | 
		
	
		
			
			|  | 191 | + * @v key		Key
 | 
		
	
		
			
			|  | 192 | + * @v keylen		Key length
 | 
		
	
		
			
			|  | 193 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 194 | + */
 | 
		
	
		
			
			|  | 195 | +static int aes_cbc_setkey ( void *ctx, const void *key, size_t keylen ) {
 | 
		
	
		
			
			|  | 196 | +	struct aes_cbc_context *aes_cbc_ctx = ctx;
 | 
		
	
		
			
			| 46 | 197 |  
 | 
		
	
		
			
			| 47 |  | -	AES_cbc_encrypt ( &aesctx->ctx, data, dst, len );
 | 
		
	
		
			
			|  | 198 | +	return cbc_setkey ( ctx, key, keylen, &aes_algorithm,
 | 
		
	
		
			
			|  | 199 | +			    &aes_cbc_ctx->cbc_ctx );
 | 
		
	
		
			
			| 48 | 200 |  }
 | 
		
	
		
			
			| 49 | 201 |  
 | 
		
	
		
			
			| 50 |  | -static void aes_cbc_decrypt ( void *ctx, const void *data, void *dst,
 | 
		
	
		
			
			|  | 202 | +/**
 | 
		
	
		
			
			|  | 203 | + * Set initialisation vector
 | 
		
	
		
			
			|  | 204 | + *
 | 
		
	
		
			
			|  | 205 | + * @v ctx		Context
 | 
		
	
		
			
			|  | 206 | + * @v iv		Initialisation vector
 | 
		
	
		
			
			|  | 207 | + */
 | 
		
	
		
			
			|  | 208 | +static void aes_cbc_setiv ( void *ctx, const void *iv ) {
 | 
		
	
		
			
			|  | 209 | +	struct aes_cbc_context *aes_cbc_ctx = ctx;
 | 
		
	
		
			
			|  | 210 | +
 | 
		
	
		
			
			|  | 211 | +	cbc_setiv ( ctx, iv, &aes_algorithm, &aes_cbc_ctx->cbc_ctx );
 | 
		
	
		
			
			|  | 212 | +}
 | 
		
	
		
			
			|  | 213 | +
 | 
		
	
		
			
			|  | 214 | +/**
 | 
		
	
		
			
			|  | 215 | + * Encrypt data
 | 
		
	
		
			
			|  | 216 | + *
 | 
		
	
		
			
			|  | 217 | + * @v ctx		Context
 | 
		
	
		
			
			|  | 218 | + * @v src		Data to encrypt
 | 
		
	
		
			
			|  | 219 | + * @v dst		Buffer for encrypted data
 | 
		
	
		
			
			|  | 220 | + * @v len		Length of data
 | 
		
	
		
			
			|  | 221 | + */
 | 
		
	
		
			
			|  | 222 | +static void aes_cbc_encrypt ( void *ctx, const void *src, void *dst,
 | 
		
	
		
			
			| 51 | 223 |  			      size_t len ) {
 | 
		
	
		
			
			| 52 |  | -	struct aes_cbc_context *aesctx = ctx;
 | 
		
	
		
			
			|  | 224 | +	struct aes_cbc_context *aes_cbc_ctx = ctx;
 | 
		
	
		
			
			| 53 | 225 |  
 | 
		
	
		
			
			| 54 |  | -	if ( ! aesctx->decrypting ) {
 | 
		
	
		
			
			| 55 |  | -		AES_convert_key ( &aesctx->ctx );
 | 
		
	
		
			
			| 56 |  | -		aesctx->decrypting = 1;
 | 
		
	
		
			
			| 57 |  | -	}
 | 
		
	
		
			
			|  | 226 | +	cbc_encrypt ( &aes_cbc_ctx->aes_ctx, src, dst, len,
 | 
		
	
		
			
			|  | 227 | +		      &aes_algorithm, &aes_cbc_ctx->cbc_ctx );
 | 
		
	
		
			
			|  | 228 | +}
 | 
		
	
		
			
			|  | 229 | +
 | 
		
	
		
			
			|  | 230 | +/**
 | 
		
	
		
			
			|  | 231 | + * Decrypt data
 | 
		
	
		
			
			|  | 232 | + *
 | 
		
	
		
			
			|  | 233 | + * @v ctx		Context
 | 
		
	
		
			
			|  | 234 | + * @v src		Data to decrypt
 | 
		
	
		
			
			|  | 235 | + * @v dst		Buffer for decrypted data
 | 
		
	
		
			
			|  | 236 | + * @v len		Length of data
 | 
		
	
		
			
			|  | 237 | + */
 | 
		
	
		
			
			|  | 238 | +static void aes_cbc_decrypt ( void *ctx, const void *src, void *dst,
 | 
		
	
		
			
			|  | 239 | +			      size_t len ) {
 | 
		
	
		
			
			|  | 240 | +	struct aes_cbc_context *aes_cbc_ctx = ctx;
 | 
		
	
		
			
			| 58 | 241 |  
 | 
		
	
		
			
			| 59 |  | -	AES_cbc_decrypt ( &aesctx->ctx, data, dst, len );
 | 
		
	
		
			
			|  | 242 | +	cbc_decrypt ( &aes_cbc_ctx->aes_ctx, src, dst, len,
 | 
		
	
		
			
			|  | 243 | +		      &aes_algorithm, &aes_cbc_ctx->cbc_ctx );
 | 
		
	
		
			
			| 60 | 244 |  }
 | 
		
	
		
			
			| 61 | 245 |  
 | 
		
	
		
			
			|  | 246 | +/* AES with cipher-block chaining */
 | 
		
	
		
			
			| 62 | 247 |  struct cipher_algorithm aes_cbc_algorithm = {
 | 
		
	
		
			
			| 63 | 248 |  	.name		= "aes_cbc",
 | 
		
	
		
			
			| 64 | 249 |  	.ctxsize	= sizeof ( struct aes_cbc_context ),
 | 
		
	
		
			
			| 65 |  | -	.blocksize	= 16,
 | 
		
	
		
			
			|  | 250 | +	.blocksize	= AES_BLOCKSIZE,
 | 
		
	
		
			
			| 66 | 251 |  	.setkey		= aes_cbc_setkey,
 | 
		
	
		
			
			| 67 | 252 |  	.setiv		= aes_cbc_setiv,
 | 
		
	
		
			
			| 68 | 253 |  	.encrypt	= aes_cbc_encrypt,
 |