Home | History | Annotate | Download | only in crypto
      1 /*
      2  * Copyright (c) 2009 Joshua Oreman <oremanj (at) rwcr.net>.
      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 
     19 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <gpxe/crypto.h>
     24 #include <gpxe/aes.h>
     25 
     26 /**
     27  * Wrap a key or other data using AES Key Wrap (RFC 3394)
     28  *
     29  * @v kek	Key Encryption Key, 16 bytes
     30  * @v src	Data to encrypt
     31  * @v nblk	Number of 8-byte blocks in @a data
     32  * @ret dest	Encrypted data (8 bytes longer than input)
     33  *
     34  * The algorithm is implemented such that @a src and @a dest may point
     35  * to the same buffer.
     36  */
     37 int aes_wrap ( const void *kek, const void *src, void *dest, int nblk )
     38 {
     39 	u8 *A = dest;
     40 	u8 B[16];
     41 	u8 *R;
     42 	int i, j;
     43 	void *aes_ctx = malloc ( AES_CTX_SIZE );
     44 
     45 	if ( ! aes_ctx )
     46 		return -1;
     47 
     48 	cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 );
     49 
     50 	/* Set up */
     51 	memset ( A, 0xA6, sizeof ( A ) );
     52 	memmove ( dest + 8, src, nblk * 8 );
     53 
     54 	/* Wrap */
     55 	for ( j = 0; j < 6; j++ ) {
     56 		R = dest + 8;
     57 		for ( i = 1; i <= nblk; i++ ) {
     58 			memcpy ( B, A, 8 );
     59 			memcpy ( B + 8, R, 8 );
     60 			cipher_encrypt ( &aes_algorithm, aes_ctx, B, B, 16 );
     61 			memcpy ( A, B, 8 );
     62 			A[7] ^= ( nblk * j ) + i;
     63 			memcpy ( R, B + 8, 8 );
     64 			R += 8;
     65 		}
     66 	}
     67 
     68 	free ( aes_ctx );
     69 	return 0;
     70 }
     71 
     72 /**
     73  * Unwrap a key or other data using AES Key Wrap (RFC 3394)
     74  *
     75  * @v kek	Key Encryption Key, 16 bytes
     76  * @v src	Data to decrypt
     77  * @v nblk	Number of 8-byte blocks in @e plaintext key
     78  * @ret dest	Decrypted data (8 bytes shorter than input)
     79  * @ret rc	Zero on success, nonzero on IV mismatch
     80  *
     81  * The algorithm is implemented such that @a src and @a dest may point
     82  * to the same buffer.
     83  */
     84 int aes_unwrap ( const void *kek, const void *src, void *dest, int nblk )
     85 {
     86 	u8 A[8], B[16];
     87 	u8 *R;
     88 	int i, j;
     89 	void *aes_ctx = malloc ( AES_CTX_SIZE );
     90 
     91 	if ( ! aes_ctx )
     92 		return -1;
     93 
     94 	cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 );
     95 
     96 	/* Set up */
     97 	memcpy ( A, src, 8 );
     98 	memmove ( dest, src + 8, nblk * 8 );
     99 
    100 	/* Unwrap */
    101 	for ( j = 5; j >= 0; j-- ) {
    102 		R = dest + ( nblk - 1 ) * 8;
    103 		for ( i = nblk; i >= 1; i-- ) {
    104 			memcpy ( B, A, 8 );
    105 			memcpy ( B + 8, R, 8 );
    106 			B[7] ^= ( nblk * j ) + i;
    107 			cipher_decrypt ( &aes_algorithm, aes_ctx, B, B, 16 );
    108 			memcpy ( A, B, 8 );
    109 			memcpy ( R, B + 8, 8 );
    110 			R -= 8;
    111 		}
    112 	}
    113 
    114 	free ( aes_ctx );
    115 
    116 	/* Check IV */
    117 	for ( i = 0; i < 8; i++ ) {
    118 		if ( A[i] != 0xA6 )
    119 			return -1;
    120 	}
    121 
    122 	return 0;
    123 }
    124