]>
Commit | Line | Data |
---|---|---|
0c1f3509 MG |
1 | #include <stdint.h> |
2 | #include <stdlib.h> | |
3 | ||
4 | #include "crypto_aes.h" | |
5 | #include "insecure_memzero.h" | |
6 | #include "sysendian.h" | |
7 | ||
8 | #include "crypto_aesctr.h" | |
9 | ||
10 | struct crypto_aesctr { | |
11 | const struct crypto_aes_key * key; | |
12 | uint64_t nonce; | |
13 | uint64_t bytectr; | |
14 | uint8_t buf[16]; | |
15 | }; | |
16 | ||
17 | /** | |
18 | * crypto_aesctr_init(key, nonce): | |
19 | * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided | |
20 | * expanded key and nonce. The key provided must remain valid for the | |
21 | * lifetime of the stream. | |
22 | */ | |
23 | struct crypto_aesctr * | |
24 | crypto_aesctr_init(const struct crypto_aes_key * key, uint64_t nonce) | |
25 | { | |
26 | struct crypto_aesctr * stream; | |
27 | ||
28 | /* Allocate memory. */ | |
29 | if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL) | |
30 | goto err0; | |
31 | ||
32 | /* Initialize values. */ | |
33 | stream->key = key; | |
34 | stream->nonce = nonce; | |
35 | stream->bytectr = 0; | |
36 | ||
37 | /* Success! */ | |
38 | return (stream); | |
39 | ||
40 | err0: | |
41 | /* Failure! */ | |
42 | return (NULL); | |
43 | } | |
44 | ||
45 | /** | |
46 | * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): | |
47 | * Generate the next ${buflen} bytes of the AES-CTR stream and xor them with | |
48 | * bytes from ${inbuf}, writing the result into ${outbuf}. If the buffers | |
49 | * ${inbuf} and ${outbuf} overlap, they must be identical. | |
50 | */ | |
51 | void | |
52 | crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, | |
53 | uint8_t * outbuf, size_t buflen) | |
54 | { | |
55 | uint8_t pblk[16]; | |
56 | size_t pos; | |
57 | int bytemod; | |
58 | ||
59 | for (pos = 0; pos < buflen; pos++) { | |
60 | /* How far through the buffer are we? */ | |
61 | bytemod = stream->bytectr % 16; | |
62 | ||
63 | /* Generate a block of cipherstream if needed. */ | |
64 | if (bytemod == 0) { | |
65 | be64enc(pblk, stream->nonce); | |
66 | be64enc(pblk + 8, stream->bytectr / 16); | |
67 | crypto_aes_encrypt_block(pblk, stream->buf, | |
68 | stream->key); | |
69 | } | |
70 | ||
71 | /* Encrypt a byte. */ | |
72 | outbuf[pos] = inbuf[pos] ^ stream->buf[bytemod]; | |
73 | ||
74 | /* Move to the next byte of cipherstream. */ | |
75 | stream->bytectr += 1; | |
76 | } | |
77 | } | |
78 | ||
79 | /** | |
80 | * crypto_aesctr_free(stream): | |
81 | * Free the provided stream object. | |
82 | */ | |
83 | void | |
84 | crypto_aesctr_free(struct crypto_aesctr * stream) | |
85 | { | |
86 | ||
87 | /* Behave consistently with free(NULL). */ | |
88 | if (stream == NULL) | |
89 | return; | |
90 | ||
91 | /* Zero potentially sensitive information. */ | |
92 | insecure_memzero(stream, sizeof(struct crypto_aesctr)); | |
93 | ||
94 | /* Free the stream. */ | |
95 | free(stream); | |
96 | } | |
97 | ||
98 | /** | |
99 | * crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen): | |
100 | * Equivalent to _init(key, nonce); _stream(inbuf, outbuf, buflen); _free(). | |
101 | */ | |
102 | void | |
103 | crypto_aesctr_buf(const struct crypto_aes_key * key, uint64_t nonce, | |
104 | const uint8_t * inbuf, uint8_t * outbuf, size_t buflen) | |
105 | { | |
106 | struct crypto_aesctr stream_rec; | |
107 | struct crypto_aesctr * stream = &stream_rec; | |
108 | ||
109 | /* Initialize values. */ | |
110 | stream->key = key; | |
111 | stream->nonce = nonce; | |
112 | stream->bytectr = 0; | |
113 | ||
114 | /* Perform the encryption. */ | |
115 | crypto_aesctr_stream(stream, inbuf, outbuf, buflen); | |
116 | ||
117 | /* Zero potentially sensitive information. */ | |
118 | insecure_memzero(stream, sizeof(struct crypto_aesctr)); | |
119 | } |