xref: /openbsd/lib/libcrypto/man/EVP_aes_128_ccm.3 (revision c0c122ca)
1.\" $OpenBSD: EVP_aes_128_ccm.3,v 1.5 2024/12/29 12:27:28 schwarze Exp $
2.\" full merge up to:
3.\" OpenSSL EVP_EncryptInit.pod 0874d7f2 Oct 11 13:13:47 2022 +0100
4.\" OpenSSL EVP_aes.pod a1ec85c1 Apr 21 10:49:12 2020 +0100
5.\"
6.\" Copyright (c) 2024 Ingo Schwarze <schwarze@openbsd.org>
7.\"
8.\" Permission to use, copy, modify, and distribute this software for any
9.\" purpose with or without fee is hereby granted, provided that the above
10.\" copyright notice and this permission notice appear in all copies.
11.\"
12.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19.\"
20.\" This file is a derived work containing a few sentences
21.\" written by Dr. Stephen Henson <steve@openssl.org>
22.\" covered by the following license:
23.\"
24.\" Copyright (c) 2012 The OpenSSL Project.  All rights reserved.
25.\"
26.\" Redistribution and use in source and binary forms, with or without
27.\" modification, are permitted provided that the following conditions
28.\" are met:
29.\"
30.\" 1. Redistributions of source code must retain the above copyright
31.\"    notice, this list of conditions and the following disclaimer.
32.\"
33.\" 2. Redistributions in binary form must reproduce the above copyright
34.\"    notice, this list of conditions and the following disclaimer in
35.\"    the documentation and/or other materials provided with the
36.\"    distribution.
37.\"
38.\" 3. All advertising materials mentioning features or use of this
39.\"    software must display the following acknowledgment:
40.\"    "This product includes software developed by the OpenSSL Project
41.\"    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
42.\"
43.\" 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
44.\"    endorse or promote products derived from this software without
45.\"    prior written permission. For written permission, please contact
46.\"    openssl-core@openssl.org.
47.\"
48.\" 5. Products derived from this software may not be called "OpenSSL"
49.\"    nor may "OpenSSL" appear in their names without prior written
50.\"    permission of the OpenSSL Project.
51.\"
52.\" 6. Redistributions of any form whatsoever must retain the following
53.\"    acknowledgment:
54.\"    "This product includes software developed by the OpenSSL Project
55.\"    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
56.\"
57.\" THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
58.\" EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
60.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
61.\" ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
62.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
64.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
66.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
67.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
68.\" OF THE POSSIBILITY OF SUCH DAMAGE.
69.\"
70.Dd $Mdocdate: December 29 2024 $
71.Dt EVP_AES_128_CCM 3
72.Os
73.Sh NAME
74.Nm EVP_aes_128_ccm ,
75.Nm EVP_aes_192_ccm ,
76.Nm EVP_aes_256_ccm
77.Nd EVP AES cipher in Counter with CBC-MAC mode
78.Sh SYNOPSIS
79.In openssl/evp.h
80.Ft const EVP_CIPHER *
81.Fn EVP_aes_128_ccm void
82.Ft const EVP_CIPHER *
83.Fn EVP_aes_192_ccm void
84.Ft const EVP_CIPHER *
85.Fn EVP_aes_256_ccm void
86.\" The following #define'd constants are intentionally undocumented:
87.\" Completely unused by anything:
88.\" EVP_CTRL_CCM_SET_MSGLEN, EVP_CCM_TLS_FIXED_IV_LEN, EVP_CCM_TLS_IV_LEN
89.\" Very rarely used and unused in LibreSSL:
90.\" EVP_CCM_TLS_EXPLICIT_IV_LEN, EVP_CCM_TLS_TAG_LEN, EVP_CCM8_TLS_TAG_LEN
91.Sh DESCRIPTION
92.Fn EVP_aes_128_ccm ,
93.Fn EVP_aes_192_ccm ,
94and
95.Fn EVP_aes_256_ccm
96provide the Advanced Encryption Standard algorithm for 128, 192 and 256-bit
97keys in Counter with CBC-MAC (CCM) mode in the
98.Xr evp 3
99framework.
100This mode supports Authenticated Encryption with Additional Data (AEAD)
101and can be used in a number of communication protocols.
102Longer keys make precomputation attacks harder at a cost in performance.
103.Pp
104For CCM mode ciphers, the behaviour of the EVP interface is subtly
105altered and several additional
106.Xr EVP_CIPHER_CTX_ctrl 3
107operations are required to function correctly.
108Some of the
109.Dv EVP_CTRL_CCM_*
110control commands are older aliases for corresponding
111.Dv EVP_CTRL_AEAD_*
112constants as indicated below.
113.Pp
114The less cumbersome and less error-prone
115.Xr EVP_AEAD_CTX_new 3
116API does not provide CCM modes.
117Some communication protocols support alternatives to CCM, which may
118sometimes allow choosing the better API by avoiding CCM.
119.Ss Configuration controls
120The following two control commands can be issued as soon as
121.Xr EVP_EncryptInit 3
122has been called with a CCM
123.Fa type
124and
125.Dv NULL
126pointers for
127.Fa key
128and
129.Fa iv .
130Both commands are optional and override each other.
131If issued when a nonce is already set, they silently cause data corruption.
132The
133.Fa ptr
134argument is ignored by both; passing
135.Dv NULL
136is recommended.
137.Bl -tag -width Ds
138.It Dv EVP_CTRL_CCM_SET_L
139Set the size
140.Ms L
141of the length field to
142.Fa arg
143bytes and the size of the nonce to
144.No 15 \- Fa arg
145bytes.
146By default, 8 bytes are used for the length field and 7 for the nonce.
147Selecting a smaller size
148.Ms L
149for the length field reduces des maximum size of messages that can be sent,
150but in return allows transmitting more messages with the same key.
151It is an error to pass less than 2 or more than the default value of 8 for
152.Fa arg .
153.It Dv EVP_CTRL_AEAD_SET_IVLEN Pq == Dv EVP_CTRL_CCM_SET_IVLEN
154Set the size of the nonce to
155.Fa arg
156bytes and the size
157.Ms L
158of the length field to
159.No 15 \- Fa arg
160bytes.
161By default, 7 bytes are used for the nonce and 8 for the length field.
162Selecting a larger size of the nonce allows transmitting more messages with
163the same key at the expense of reducing the maximum size for each message.
164It is an error to pass more than 13 or less than the default value of 7 for
165.Fa arg .
166.El
167.Pp
168After optionally issuing one of the above control commands,
169.Xr EVP_EncryptInit 3
170can be called a second time, this time passing
171.Dv NULL
172for the
173.Fa type
174argument, with the other two arguments pointing to the desired AES key
175and to the desired nonce.
176.Ss Encryption controls
177.Bl -tag -width Ds
178.It Dv EVP_CTRL_AEAD_SET_TAG Pq == Dv EVP_CTRL_CCM_SET_TAG
179If the
180.Fa ptr
181argument is
182.Dv NULL ,
183set the tag length
184.Ms M
185to
186.Fa arg
187bytes.
188The default value is 12.
189Selecting a larger value makes tampering harder for an attacker,
190at a small expense of making the messages slightly longer.
191Selecting a smaller value is not recommended.
192It is an error to pass an odd number for
193.Fa arg ,
194or a number that is less than 4 or greater than 16, or to pass
195.Dv NULL
196to
197.Fa ptr
198when
199.Fa ctx
200is not configured for encrypting.
201Issuing this control command when an encryption key is already configured
202silently causes data corruption.
203.It Dv EVP_CTRL_AEAD_GET_TAG Pq == Dv EVP_CTRL_CCM_GET_TAG
204Store the
205.Fa arg
206bytes of the tag in the memory provided by the caller starting at
207.Fa ptr .
208It is an error to issue this control command when
209.Fa ctx
210is not configured for encrypting, when no data was encrypted yet, with an
211.Fa arg
212that does not match the configured tag length
213.Ms M ,
214or when the tag has already been retrieved earlier.
215.El
216.Pp
217Before passing any plaintext data to
218.Xr EVP_EncryptUpdate 3 ,
219call
220.Xr EVP_EncryptUpdate 3
221with both
222.Fa in
223and
224.Fa out
225set to
226.Dv NULL ,
227passing the total plaintext length in bytes as
228.Fa in_len .
229This constructs the first block to be digested with CBC-MAC
230and copies the text length to
231.Pf * Fa out_len .
232It does not check whether
233.Fa in_len
234exceeds the limit of
235.Pf 256\(ha Ms L ;
236the most significant bytes of excessive values are silently discarded.
237.Pp
238It is an error if the
239.Fa in_len
240argument of the
241.Xr EVP_EncryptUpdate 3
242call passing the plaintext data does not match the total length
243specified earlier.
244Splitting the text into more than one chunks to be passed in multiple calls of
245.Xr EVP_EncryptUpdate 3
246is not supported for CCM.
247.Pp
248To specify any additional authenticated data (AAD), call
249.Xr EVP_EncryptUpdate 3
250with the
251.Fa out
252argument set to
253.Dv NULL .
254.Ss Decryption controls
255.Bl -tag -width Ds
256.It Dv EVP_CTRL_AEAD_SET_TAG Pq == Dv EVP_CTRL_CCM_SET_TAG
257If the
258.Fa ptr
259argument is not
260.Dv NULL ,
261copy
262.Fa arg
263bytes starting at
264.Fa ptr
265to the expected CCM tag value.
266It is an error to pass an odd number for
267.Fa arg ,
268or a number that is less than 4 or greater than 16.
269Passing a number that does not correspond to the tag length
270.Ms M
271that was used for encryption does not raise an error right away,
272but results in undefined behaviour
273and typically causes subsequent authentication failure.
274It is also an error to pass a
275.Pf non- Dv NULL
276.Fa ptr
277when
278.Fa ctx
279is configured for encryption.
280.El
281.Pp
282Before passing any ciphertext data to
283.Xr EVP_DecryptUpdate 3 ,
284call
285.Xr EVP_DecryptUpdate 3
286with both
287.Fa in
288and
289.Fa out
290set to
291.Dv NULL ,
292passing the total ciphertext length in bytes as
293.Fa in_len .
294This constructs the first block to be digested with CBC-MAC
295and copies the text length to
296.Pf * Fa out_len .
297It does not check whether
298.Fa in_len
299exceeds the limit of
300.Pf 256\(ha Ms L ;
301the most significant bytes of excessive values are silently discarded.
302.Pp
303It is an error if the
304.Fa in_len
305argument of the
306.Xr EVP_DecryptUpdate 3
307call passing the ciphertext data does not match the total length
308specified earlier.
309Splitting the text into more than one chunks to be passed in multiple calls of
310.Xr EVP_DecryptUpdate 3
311is not supported for CCM.
312.Pp
313To specify any additional authenticated data (AAD), call
314.Xr EVP_DecryptUpdate 3
315with the
316.Fa out
317argument set to
318.Dv NULL .
319.Pp
320If the return value of
321.Xr EVP_DecryptUpdate 3
322does not indicate success, the authentication operation may have failed.
323In that case, regard any output data as corrupted.
324.Pp
325Do not call
326.Xr EVP_DecryptFinal 3
327when using CCM.
328Such a call would not do anything useful, and it would fail
329because the tag that was set with
330.Dv EVP_CTRL_CCM_SET_TAG
331was already consumed by
332.Xr EVP_DecryptUpdate 3 .
333.Sh RETURN VALUES
334These functions return a static constant
335.Vt EVP_CIPHER
336structure that provides the implementation of the respective AEAD cipher mode.
337.Sh EXAMPLES
338The following code encrypts and digests some secret text
339and some additional, public data with AES-CCM.
340Specifically, it implements the Test Vector #1
341given in section 8 of RFC 3610.
342.Bd -literal -offset indent
343/* input data */
344const unsigned char key[] = {
345    0xC0, 0xC1, 0xC2, 0xC3,  0xC4, 0xC5, 0xC6, 0xC7,
346    0xC8, 0xC9, 0xCA, 0xCB,  0xCC, 0xCD, 0xCE, 0xCF
347};
348const unsigned char nonce[] = {
349    0x00, 0x00, 0x00, 0x03,  0x02, 0x01, 0x00, 0xA0,
350    0xA1, 0xA2, 0xA3, 0xA4,  0xA5
351};
352const int nonce_len = sizeof(nonce);
353const int size_len = 15 - nonce_len;
354
355const unsigned char aad[] = {
356    0x00, 0x01, 0x02, 0x03,  0x04, 0x05, 0x06, 0x07
357};
358const int aad_len = sizeof(aad);
359
360const unsigned char plaintext[] = {
361    0x08, 0x09, 0x0A, 0x0B,  0x0C, 0x0D, 0x0E, 0x0F,
362    0x10, 0x11, 0x12, 0x13,  0x14, 0x15, 0x16, 0x17,
363    0x18, 0x19, 0x1A, 0x1B,  0x1C, 0x1D, 0x1E
364};
365const int text_len = sizeof(plaintext);
366
367/* expected output data */
368const unsigned char ciphertext[] = {
369    0x58, 0x8C, 0x97, 0x9A,  0x61, 0xC6, 0x63, 0xD2,
370    0xF0, 0x66, 0xD0, 0xC2,  0xC0, 0xF9, 0x89, 0x80,
371    0x6D, 0x5F, 0x6B, 0x61,  0xDA, 0xC3, 0x84
372};
373
374const unsigned char wanted_tag[] = {
375    0x17, 0xE8, 0xD1, 0x2C,  0xFD, 0xF9, 0x26, 0xE0
376};
377const int tag_len = sizeof(wanted_tag);
378
379const int out_len = aad_len + text_len + tag_len;
380unsigned char out_buf[out_len];
381unsigned char *out_p = out_buf;
382unsigned char *out_end = out_buf + out_len;
383
384/* auxiliary variables */
385EVP_CIPHER_CTX *ctx;
386int irv, i;
387
388/* configuration */
389ctx = EVP_CIPHER_CTX_new();
390if (ctx == NULL)
391	err(1, "EVP_CIPHER_CTX_new");
392
393if (EVP_EncryptInit(ctx, EVP_aes_128_ccm(), NULL, NULL) != 1)
394	err(1, "EVP_EncryptInit(NULL)");
395
396if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L,
397    size_len, NULL) <= 0)
398	err(1, "EVP_CTRL_CCM_SET_L(%d)", size_len);
399
400if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG,
401    tag_len, NULL) <= 0)
402	err(1, "EVP_CTRL_CCM_SET_TAG(%d)", tag_len);
403
404/* process input data */
405if (EVP_EncryptInit(ctx, NULL, key, nonce) != 1)
406	err(1, "EVP_EncryptInit(key, nonce)");
407
408if (EVP_EncryptUpdate(ctx, NULL, &irv, NULL, text_len) != 1)
409	err(1, "EVP_EncryptUpdate(len = %d)", text_len);
410if (irv != text_len)
411	errx(1, "text length: want %d, got %d", text_len, irv);
412
413irv = -1;
414if (EVP_EncryptUpdate(ctx, NULL, &irv, aad, aad_len) != 1)
415	err(1, "EVP_EncryptUpdate(AAD)");
416memcpy(out_p, aad, aad_len);
417out_p += aad_len;
418
419irv = -1;
420if (EVP_EncryptUpdate(ctx, out_p, &irv, plaintext, text_len) != 1)
421	err(1, "EVP_EncryptUpdate(plaintext)");
422if (irv != text_len)
423	errx(1, "text_len: want %d, got %d", text_len, irv);
424out_p += irv;
425
426/*
427 * EVP_EncryptFinal(3) doesn't really do anything for CCM.
428 * Call it anyway to stay closer to normal EVP_Encrypt*(3) idioms,
429 * to match what the OpenSSL Wiki suggests since 2013, and to ease
430 * later migration of the code to a different AEAD algorithm.
431 */
432irv = -1;
433if (EVP_EncryptFinal(ctx, out_p, &irv) != 1)
434	err(1, "EVP_EncryptFinal");
435if (irv != 0)
436	errx(1, "final_len: want 0, got %d", irv);
437
438/* check output data */
439if (memcmp(out_buf + aad_len, ciphertext, text_len) != 0)
440	errx(1, "ciphertext mismatch");
441
442if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG,
443    tag_len, out_p) <= 0)
444	err(1, "EVP_CTRL_CCM_GET_TAG");
445if (memcmp(out_p, wanted_tag, tag_len) != 0)
446	errx(1, "tag mismatch");
447out_p += tag_len;
448if (out_p != out_end)
449	errx(1, "end of output: want %p, got %p", out_end, out_p);
450
451printf("Total packet length = %d.", out_len);
452printf(" [Authenticated and Encrypted Output]");
453for (i = 0; i < out_len; i++) {
454	if (i % 16 == 0)
455		printf("\en         ");
456	if (i % 4 == 0)
457		putchar(' ');
458	printf(" %02X", out_buf[i]);
459}
460putchar('\en');
461
462EVP_CIPHER_CTX_free(ctx);
463.Ed
464.Pp
465The reverse operation for the same test vector,
466i.e. decrypting and comparing the digest,
467is implemented by the following code.
468.Pp
469The variable declarations and definitions up to the call of
470.Xr EVP_CIPHER_CTX_new 3
471are the same as above.
472The chief differences are:
473.Bl -dash -width 1n -compact
474.It
475The tag is not part of the output,
476so the total output length is shorter.
477.It
478No
479.Xr memcmp 3
480of the tag takes place.
481Instead, the control command
482.Dv EVP_CTRL_CCM_SET_TAG
483requires the tag that is going to be verified as an additional argument.
484.It
485While
486.Xr EVP_EncryptFinal 3
487is an optional no-op,
488.Xr EVP_DecryptFinal 3
489is not called and would fail.
490.El
491.Bd -literal -offset indent
492const int out_len = aad_len + text_len;
493
494/* configuration */
495ctx = EVP_CIPHER_CTX_new();
496if (ctx == NULL)
497	err(1, "EVP_CIPHER_CTX_new");
498
499if (EVP_DecryptInit(ctx, EVP_aes_128_ccm(), NULL, NULL) != 1)
500	err(1, "EVP_DecryptInit(NULL)");
501
502if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, size_len, NULL) <= 0)
503	err(1, "EVP_CTRL_CCM_SET_L(%d)", size_len);
504
505if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG,
506    tag_len, (void *)wanted_tag) <= 0)
507	err(1, "EVP_CTRL_CCM_SET_TAG(%d)", tag_len);
508
509/* process input data */
510if (EVP_DecryptInit(ctx, NULL, key, nonce) != 1)
511	err(1, "EVP_DecryptInit(key, nonce)");
512
513if (EVP_DecryptUpdate(ctx, NULL, &irv, NULL, text_len) != 1)
514	err(1, "EVP_DecryptUpdate(len = %d)", text_len);
515if (irv != text_len)
516	errx(1, "text length: want %d, got %d", text_len, irv);
517
518irv = -1;
519if (EVP_DecryptUpdate(ctx, NULL, &irv, aad, aad_len) != 1)
520	err(1, "EVP_DecryptUpdate(AAD)");
521memcpy(out_p, aad, aad_len);
522out_p += aad_len;
523
524irv = -1;
525if (EVP_DecryptUpdate(ctx, out_p, &irv, ciphertext, text_len) != 1)
526	err(1, "EVP_DecryptUpdate(ciphertext)");
527if (irv != text_len)
528	errx(1, "text_len: want %d, got %d", text_len, irv);
529out_p += irv;
530
531/* Do not call EVP_DecryptFinal(3); it would fail and do nothing. */
532
533/* check output data */
534if (memcmp(out_buf + aad_len, plaintext, text_len) != 0)
535	errx(1, "plaintext mismatch");
536if (out_p != out_end)
537	errx(1, "end of output: want %p, got %p", out_end, out_p);
538
539printf("Total packet length = %d.", out_len);
540printf(" [Decrypted and Authenticated Input]");
541for (i = 0; i < out_len; i++) {
542	if (i % 16 == 0)
543		printf("\n         ");
544	if (i % 4 == 0)
545		putchar(' ');
546	printf(" %02X", out_buf[i]);
547}
548putchar('\n');
549
550EVP_CIPHER_CTX_free(ctx);
551.Ed
552.Sh SEE ALSO
553.Xr AES_encrypt 3 ,
554.Xr evp 3 ,
555.Xr EVP_aes_128_cbc 3 ,
556.Xr EVP_aes_128_gcm 3 ,
557.Xr EVP_EncryptInit 3
558.Sh STANDARDS
559.Rs
560.%A Doug Whiting
561.%A Russ Housley
562.%A Niels Ferguson
563.%T Counter with CBC-MAC (CCM)
564.%R RFC 3610
565.%D September 2003
566.Re
567.Sh HISTORY
568.Fn EVP_aes_128_ccm ,
569.Fn EVP_aes_192_ccm ,
570and
571.Fn EVP_aes_256_ccm
572first appeared in OpenSSL 1.0.1 and have been available since
573.Ox 5.3 .
574