1 /* Copyright (c) 2018, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include <openssl/aead.h>
16 
17 #include <assert.h>
18 
19 #include <openssl/cipher.h>
20 #include <openssl/err.h>
21 #include <openssl/mem.h>
22 
23 #include "../fipsmodule/cipher/internal.h"
24 
25 
26 #define EVP_AEAD_AES_CCM_MAX_TAG_LEN 16
27 
28 struct aead_aes_ccm_ctx {
29   union {
30     double align;
31     AES_KEY ks;
32   } ks;
33   CCM128_CONTEXT ccm;
34 };
35 
36 OPENSSL_STATIC_ASSERT(sizeof(((EVP_AEAD_CTX *)NULL)->state) >=
37                           sizeof(struct aead_aes_ccm_ctx),
38                       "AEAD state is too small");
39 #if defined(__GNUC__) || defined(__clang__)
40 OPENSSL_STATIC_ASSERT(alignof(union evp_aead_ctx_st_state) >=
41                           alignof(struct aead_aes_ccm_ctx),
42                       "AEAD state has insufficient alignment");
43 #endif
44 
aead_aes_ccm_init(EVP_AEAD_CTX * ctx,const uint8_t * key,size_t key_len,size_t tag_len,unsigned M,unsigned L)45 static int aead_aes_ccm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
46                              size_t key_len, size_t tag_len, unsigned M,
47                              unsigned L) {
48   assert(M == EVP_AEAD_max_overhead(ctx->aead));
49   assert(M == EVP_AEAD_max_tag_len(ctx->aead));
50   assert(15 - L == EVP_AEAD_nonce_length(ctx->aead));
51 
52   if (key_len != EVP_AEAD_key_length(ctx->aead)) {
53     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
54     return 0;  // EVP_AEAD_CTX_init should catch this.
55   }
56 
57   if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
58     tag_len = M;
59   }
60 
61   if (tag_len != M) {
62     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
63     return 0;
64   }
65 
66   struct aead_aes_ccm_ctx *ccm_ctx = (struct aead_aes_ccm_ctx *)&ctx->state;
67 
68   block128_f block;
69   ctr128_f ctr = aes_ctr_set_key(&ccm_ctx->ks.ks, NULL, &block, key, key_len);
70   ctx->tag_len = tag_len;
71   if (!CRYPTO_ccm128_init(&ccm_ctx->ccm, &ccm_ctx->ks.ks, block, ctr, M, L)) {
72     OPENSSL_PUT_ERROR(CIPHER, ERR_R_INTERNAL_ERROR);
73     return 0;
74   }
75 
76   return 1;
77 }
78 
aead_aes_ccm_cleanup(EVP_AEAD_CTX * ctx)79 static void aead_aes_ccm_cleanup(EVP_AEAD_CTX *ctx) {}
80 
aead_aes_ccm_seal_scatter(const EVP_AEAD_CTX * ctx,uint8_t * out,uint8_t * out_tag,size_t * out_tag_len,size_t max_out_tag_len,const uint8_t * nonce,size_t nonce_len,const uint8_t * in,size_t in_len,const uint8_t * extra_in,size_t extra_in_len,const uint8_t * ad,size_t ad_len)81 static int aead_aes_ccm_seal_scatter(
82     const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
83     size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
84     size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
85     size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
86   const struct aead_aes_ccm_ctx *ccm_ctx =
87       (struct aead_aes_ccm_ctx *)&ctx->state;
88 
89   if (in_len > CRYPTO_ccm128_max_input(&ccm_ctx->ccm)) {
90     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
91     return 0;
92   }
93 
94   if (max_out_tag_len < ctx->tag_len) {
95     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
96     return 0;
97   }
98 
99   if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
100     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
101     return 0;
102   }
103 
104   if (!CRYPTO_ccm128_encrypt(&ccm_ctx->ccm, &ccm_ctx->ks.ks, out, out_tag,
105                              ctx->tag_len, nonce, nonce_len, in, in_len, ad,
106                              ad_len)) {
107     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
108     return 0;
109   }
110 
111   *out_tag_len = ctx->tag_len;
112   return 1;
113 }
114 
aead_aes_ccm_open_gather(const EVP_AEAD_CTX * ctx,uint8_t * out,const uint8_t * nonce,size_t nonce_len,const uint8_t * in,size_t in_len,const uint8_t * in_tag,size_t in_tag_len,const uint8_t * ad,size_t ad_len)115 static int aead_aes_ccm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
116                                     const uint8_t *nonce, size_t nonce_len,
117                                     const uint8_t *in, size_t in_len,
118                                     const uint8_t *in_tag, size_t in_tag_len,
119                                     const uint8_t *ad, size_t ad_len) {
120   const struct aead_aes_ccm_ctx *ccm_ctx =
121       (struct aead_aes_ccm_ctx *)&ctx->state;
122 
123   if (in_len > CRYPTO_ccm128_max_input(&ccm_ctx->ccm)) {
124     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
125     return 0;
126   }
127 
128   if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
129     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
130     return 0;
131   }
132 
133   if (in_tag_len != ctx->tag_len) {
134     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
135     return 0;
136   }
137 
138   uint8_t tag[EVP_AEAD_AES_CCM_MAX_TAG_LEN];
139   assert(ctx->tag_len <= EVP_AEAD_AES_CCM_MAX_TAG_LEN);
140   if (!CRYPTO_ccm128_decrypt(&ccm_ctx->ccm, &ccm_ctx->ks.ks, out, tag,
141                              ctx->tag_len, nonce, nonce_len, in, in_len, ad,
142                              ad_len)) {
143     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
144     return 0;
145   }
146 
147   if (CRYPTO_memcmp(tag, in_tag, ctx->tag_len) != 0) {
148     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
149     return 0;
150   }
151 
152   return 1;
153 }
154 
aead_aes_ccm_bluetooth_init(EVP_AEAD_CTX * ctx,const uint8_t * key,size_t key_len,size_t tag_len)155 static int aead_aes_ccm_bluetooth_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
156                                        size_t key_len, size_t tag_len) {
157   return aead_aes_ccm_init(ctx, key, key_len, tag_len, 4, 2);
158 }
159 
160 static const EVP_AEAD aead_aes_128_ccm_bluetooth = {
161     16,  // key length (AES-128)
162     13,  // nonce length
163     4,   // overhead
164     4,   // max tag length
165     0,   // seal_scatter_supports_extra_in
166 
167     aead_aes_ccm_bluetooth_init,
168     NULL /* init_with_direction */,
169     aead_aes_ccm_cleanup,
170     NULL /* open */,
171     aead_aes_ccm_seal_scatter,
172     aead_aes_ccm_open_gather,
173     NULL /* get_iv */,
174     NULL /* tag_len */,
175 };
176 
EVP_aead_aes_128_ccm_bluetooth(void)177 const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth(void) {
178   return &aead_aes_128_ccm_bluetooth;
179 }
180 
aead_aes_ccm_bluetooth_8_init(EVP_AEAD_CTX * ctx,const uint8_t * key,size_t key_len,size_t tag_len)181 static int aead_aes_ccm_bluetooth_8_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
182                                          size_t key_len, size_t tag_len) {
183   return aead_aes_ccm_init(ctx, key, key_len, tag_len, 8, 2);
184 }
185 
186 static const EVP_AEAD aead_aes_128_ccm_bluetooth_8 = {
187     16,  // key length (AES-128)
188     13,  // nonce length
189     8,   // overhead
190     8,   // max tag length
191     0,   // seal_scatter_supports_extra_in
192 
193     aead_aes_ccm_bluetooth_8_init,
194     NULL /* init_with_direction */,
195     aead_aes_ccm_cleanup,
196     NULL /* open */,
197     aead_aes_ccm_seal_scatter,
198     aead_aes_ccm_open_gather,
199     NULL /* get_iv */,
200     NULL /* tag_len */,
201 };
202 
EVP_aead_aes_128_ccm_bluetooth_8(void)203 const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth_8(void) {
204   return &aead_aes_128_ccm_bluetooth_8;
205 }
206