Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / tests / cbc_test.c
1 /*
2  * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 /** @file
23  *
24  * CBC self-tests
25  *
26  */
27
28 /* Forcibly enable assertions */
29 #undef NDEBUG
30
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <assert.h>
35 #include <ipxe/crypto.h>
36 #include <ipxe/profile.h>
37 #include "cbc_test.h"
38
39 /** Number of sample iterations for profiling */
40 #define PROFILE_COUNT 16
41
42 /**
43  * Test CBC encryption
44  *
45  * @v cipher                    Cipher algorithm
46  * @v key                       Key
47  * @v key_len                   Length of key
48  * @v iv                        Initialisation vector
49  * @v plaintext                 Plaintext data
50  * @v expected_ciphertext       Expected ciphertext data
51  * @v len                       Length of data
52  * @ret ok                      Ciphertext is as expected
53  */
54 int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key,
55                        size_t key_len, const void *iv, const void *plaintext,
56                        const void *expected_ciphertext, size_t len ) {
57         uint8_t ctx[cipher->ctxsize];
58         uint8_t ciphertext[len];
59         int rc;
60
61         /* Initialise cipher */
62         rc = cipher_setkey ( cipher, ctx, key, key_len );
63         assert ( rc == 0 );
64         cipher_setiv ( cipher, ctx, iv );
65
66         /* Perform encryption */
67         cipher_encrypt ( cipher, ctx, plaintext, ciphertext, len );
68
69         /* Verify result */
70         return ( memcmp ( ciphertext, expected_ciphertext, len ) == 0 );
71 }
72
73 /**
74  * Test CBC decryption
75  *
76  * @v cipher                    Cipher algorithm
77  * @v key                       Key
78  * @v key_len                   Length of key
79  * @v iv                        Initialisation vector
80  * @v ciphertext                Ciphertext data
81  * @v expected_plaintext        Expected plaintext data
82  * @v len                       Length of data
83  * @ret ok                      Plaintext is as expected
84  */
85 int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key,
86                        size_t key_len, const void *iv, const void *ciphertext,
87                        const void *expected_plaintext, size_t len ) {
88         uint8_t ctx[cipher->ctxsize];
89         uint8_t plaintext[len];
90         int rc;
91
92         /* Initialise cipher */
93         rc = cipher_setkey ( cipher, ctx, key, key_len );
94         assert ( rc == 0 );
95         cipher_setiv ( cipher, ctx, iv );
96
97         /* Perform encryption */
98         cipher_decrypt ( cipher, ctx, ciphertext, plaintext, len );
99
100         /* Verify result */
101         return ( memcmp ( plaintext, expected_plaintext, len ) == 0 );
102 }
103
104 /**
105  * Calculate CBC encryption or decryption cost
106  *
107  * @v cipher                    Cipher algorithm
108  * @v key_len                   Length of key
109  * @v op                        Encryption or decryption operation
110  * @ret cost                    Cost (in cycles per byte)
111  */
112 static unsigned long cbc_cost ( struct cipher_algorithm *cipher,
113                                 size_t key_len,
114                                 void ( * op ) ( struct cipher_algorithm *cipher,
115                                                 void *ctx, const void *src,
116                                                 void *dst, size_t len ) ) {
117         static uint8_t random[8192]; /* Too large for stack */
118         uint8_t key[key_len];
119         uint8_t iv[cipher->blocksize];
120         uint8_t ctx[cipher->ctxsize];
121         struct profiler profiler;
122         unsigned long cost;
123         unsigned int i;
124         int rc;
125
126         /* Fill buffer with pseudo-random data */
127         srand ( 0x1234568 );
128         for ( i = 0 ; i < sizeof ( random ) ; i++ )
129                 random[i] = rand();
130         for ( i = 0 ; i < sizeof ( key ) ; i++ )
131                 key[i] = rand();
132         for ( i = 0 ; i < sizeof ( iv ) ; i++ )
133                 iv[i] = rand();
134
135         /* Initialise cipher */
136         rc = cipher_setkey ( cipher, ctx, key, key_len );
137         assert ( rc == 0 );
138         cipher_setiv ( cipher, ctx, iv );
139
140         /* Profile cipher operation */
141         memset ( &profiler, 0, sizeof ( profiler ) );
142         for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
143                 profile_start ( &profiler );
144                 op ( cipher, ctx, random, random, sizeof ( random ) );
145                 profile_stop ( &profiler );
146         }
147
148         /* Round to nearest whole number of cycles per byte */
149         cost = ( ( profile_mean ( &profiler ) + ( sizeof ( random ) / 2 ) ) /
150                  sizeof ( random ) );
151
152         return cost;
153 }
154
155 /**
156  * Calculate CBC encryption cost
157  *
158  * @v cipher                    Cipher algorithm
159  * @v key_len                   Length of key
160  * @ret cost                    Cost (in cycles per byte)
161  */
162 unsigned long cbc_cost_encrypt ( struct cipher_algorithm *cipher,
163                                  size_t key_len ) {
164         return cbc_cost ( cipher, key_len, cipher_encrypt );
165 }
166
167 /**
168  * Calculate CBC decryption cost
169  *
170  * @v cipher                    Cipher algorithm
171  * @v key_len                   Length of key
172  * @ret cost                    Cost (in cycles per byte)
173  */
174 unsigned long cbc_cost_decrypt ( struct cipher_algorithm *cipher,
175                                  size_t key_len ) {
176         return cbc_cost ( cipher, key_len, cipher_decrypt );
177 }