1
0
mirror of https://github.com/openbsd/src.git synced 2024-12-22 07:27:59 -08:00

Add an EXAMPLES section.

I admit this is unusually long for a manual page.  But that's not my fault
as a documentation author.  An example in a manual page ought to be minimal
to show what needs to be demonstrated, and this example is minimal in that
sense.  Making it shorter without loosing important aspects does not seem
possible.

When an API is poorly designed, one of the consequences is that that
documentation becomes harder to understand and often longer - in this
case to the point of becoming outright intimidating.  If people dislike
that, they should design better APIs in the first place rather than
blasting the poor manual page for being too long or too complicated.

OK tb@
This commit is contained in:
schwarze 2024-12-21 00:27:47 +00:00
parent 8ee0399bd2
commit a63b39658a

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: EVP_aes_128_ccm.3,v 1.1 2024/12/20 01:54:03 schwarze Exp $
.\" $OpenBSD: EVP_aes_128_ccm.3,v 1.2 2024/12/21 00:27:47 schwarze Exp $
.\" full merge up to:
.\" OpenSSL EVP_EncryptInit.pod 0874d7f2 Oct 11 13:13:47 2022 +0100
.\" OpenSSL EVP_aes.pod a1ec85c1 Apr 21 10:49:12 2020 +0100
@ -67,7 +67,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: December 20 2024 $
.Dd $Mdocdate: December 21 2024 $
.Dt EVP_AES_128_CCM 3
.Os
.Sh NAME
@ -324,6 +324,133 @@ was already consumed by
These functions return a static constant
.Vt EVP_CIPHER
structure that provides the implementation of the respective AEAD cipher mode.
.Sh EXAMPLES
The following code encrypts and digests some secret text
and some additional, public data with AES-CCM.
Specifically, it implements the Test Vector #1
given in section 8 of RFC 3610.
.Bd -literal -offset indent
/* input data */
const unsigned char key[] = {
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
};
const unsigned char nonce[] = {
0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0,
0xA1, 0xA2, 0xA3, 0xA4, 0xA5
};
const int nonce_len = sizeof(nonce);
const int size_len = 15 - nonce_len;
const unsigned char aad[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
const int aad_len = sizeof(aad);
const unsigned char plaintext[] = {
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E
};
const int text_len = sizeof(plaintext);
/* expected output data */
const unsigned char ciphertext[] = {
0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2,
0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80,
0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84
};
const unsigned char wanted_tag[] = {
0x17, 0xE8, 0xD1, 0x2C, 0xFD, 0xF9, 0x26, 0xE0
};
const int tag_len = sizeof(wanted_tag);
const int out_len = aad_len + text_len + tag_len;
unsigned char out_buf[out_len];
unsigned char *out_p = out_buf;
unsigned char *out_end = out_buf + out_len;
/* auxiliary variables */
EVP_CIPHER_CTX *ctx;
int irv, i;
/* configuration */
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
err(1, "EVP_CIPHER_CTX_new");
if (EVP_EncryptInit(ctx, EVP_aes_128_ccm(), NULL, NULL) != 1)
err(1, "EVP_EncryptInit(NULL)");
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L,
size_len, NULL) <= 0)
err(1, "EVP_CTRL_CCM_SET_L(%d)", size_len);
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG,
tag_len, NULL) <= 0)
err(1, "EVP_CTRL_CCM_SET_TAG(%d)", tag_len);
/* process input data */
if (EVP_EncryptInit(ctx, NULL, key, nonce) != 1)
err(1, "EVP_EncryptInit(key, nonce)");
if (EVP_EncryptUpdate(ctx, NULL, &irv, NULL, text_len) != 1)
err(1, "EVP_EncryptUpdate(len = %d)", text_len);
if (irv != text_len)
errx(1, "text length: want %d, got %d", text_len, irv);
irv = -1;
if (EVP_EncryptUpdate(ctx, NULL, &irv, aad, aad_len) != 1)
err(1, "EVP_EncryptUpdate(AAD)");
memcpy(out_p, aad, aad_len);
out_p += aad_len;
irv = -1;
if (EVP_EncryptUpdate(ctx, out_p, &irv, plaintext, text_len) != 1)
err(1, "EVP_EncryptUpdate(plaintext)");
if (irv != text_len)
errx(1, "text_len: want %d, got %d", text_len, irv);
out_p += irv;
/*
* EVP_EncryptFinal(3) doesn't really do anything for CCM.
* Call it anyway to stay closer to normal EVP_Encrypt*(3) idioms,
* to match what the OpenSSL Wiki suggests since 2013, and to ease
* later migration of the code to a different AEAD algorithm.
*/
irv = -1;
if (EVP_EncryptFinal(ctx, out_p, &irv) != 1)
err(1, "EVP_EncryptFinal");
if (irv != 0)
errx(1, "final_len: want 0, got %d", irv);
/* check output data */
if (memcmp(out_buf + aad_len, ciphertext, text_len) != 0)
errx(1, "ciphertext mismatch");
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG,
tag_len, out_p) <= 0)
err(1, "EVP_CTRL_CCM_GET_TAG");
if (memcmp(out_p, wanted_tag, tag_len) != 0)
errx(1, "tag mismatch");
out_p += tag_len;
if (out_p != out_end)
errx(1, "end of output: want %p, got %p", out_end, out_p);
printf("Total packet length = %d.", out_len);
printf(" [Authenticated and Encrypted Output]");
for (i = 0; i < out_len; i++) {
if (i % 16 == 0)
printf("\en ");
if (i % 4 == 0)
putchar(' ');
printf(" %02X", out_buf[i]);
}
putchar('\en');
EVP_CIPHER_CTX_free(ctx);
.Ed
.Sh SEE ALSO
.Xr AES_encrypt 3 ,
.Xr evp 3 ,