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