Here's a first stab at assembling some documentation about CCM mode and its API.
It's probably still in need some some good proofreading for grammar and consistency.
Some minor nits that I noticed about the API while writing it:
- ccm_decrypt_message uses const void * for the cipher context, but all the
other interfaces use void * for this.
- passing the clength rather mlength to ccm_decrypt_message could be a little
confusing when compared to the rest of the API. In retrospect, I think Neils's
initial suggestion on this API was probably the better way to go.
Cheers,
Owen
>From 0b0651a6e754652d9ce1aa7c2f6f7cbc3fc498bc Mon Sep 17 00:00:00 2001
From: Owen Kirby <osk(a)exegin.com>
Date: Sat, 12 Apr 2014 21:31:39 -0700
Subject: [PATCH] Added CCM mode to the documentation.
---
nettle.texinfo | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 224 insertions(+), 1 deletion(-)
diff --git a/nettle.texinfo b/nettle.texinfo
index 68883a5..c988eb6 100644
--- a/nettle.texinfo
+++ b/nettle.texinfo
@@ -88,6 +88,7 @@ Cipher modes
* CBC::
* CTR::
* GCM::
+* CCM::
Public-key algorithms
@@ -1788,6 +1789,7 @@ signature to authenticate the message.
* CBC::
* CTR::
* GCM::
+* CCM::
@end menu
@@ -1960,7 +1962,7 @@ last three arguments define the source and destination area for the
operation.
@end deffn
-@node GCM, , CTR, Cipher modes
+@node GCM, CCM, CTR, Cipher modes
@comment node-name, next, previous, up
@subsection Galois counter mode
@@ -2153,7 +2155,228 @@ equal to @code{GCM_BLOCK_SIZE}, but if you provide a smaller value,
only the first @var{length} octets of the digest are written.
@end deftypefun
+@node CCM, , GCM, Cipher modes
+@comment node-name, next, previous, up
+@subsection Counter with CBC-MAC mode
+
+@cindex Counter with CBC-MAC Mode
+@cindex CCM Mode
+
+CCM mode is the combination of counter mode with message authentication based on
+cipher block chaining. It is constructed on top of a block cipher which must
+have a block size of 128 bits. @acronym{CCM} mode is recommended by NIST in
+@uref{http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf,
+NIST Special Publication 800-38C}. Nettle's support for CCM consists of a
+low-level general interface, a message encryption and authentication interface,
+and specific functions for CCM using AES as the underlying block cipher. These
+interfaces are defined in @file{<nettle/ccm.h>}
+
+The inputs to @acronym{CCM} are:
+@itemize
+@item
+A key, which can be used for many messages.
+@item
+A parameter @var{L} which determines the size of the nonce and the maximum
+length of message data which can be processed by @acronym{CCM}.
+@item
+A tag length, which must be a multiple of 4 bytes up to a maximum of one block.
+@item
+A nonce which @emph{must} be unique for each message.
+@item
+Optional authenticated data, which is to be included in the message
+authentication, but not encrypted.
+@item
+The plaintext. May be empty.
+@end itemize
+
+The outputs from @acronym{CCM} are:
+@itemize
+@item
+The ciphertext of the same length as the plaintext.
+@item
+An encrypted authentication tag, up to one block on length.
+@end itemize
+
+The parameter @var{L} determines the size of the counter that is used for the
+message length, such that the maximum message length in bytes is given by
+@code{maxlength = (1 << L) - 1}. However increasing @var{L} also restricts the
+size of the nonce such that @code{noncelength = CCM_BLOCK_SIZE - 1 - L}, and
+throughout this interface the parameter @var{L} is provided implicitly by the
+nonce length.
+
+@acronym{CCM} mode encryption operates as follows:
+@itemize
+@item The nonce and message length are concatenated to create
+ @code{B_0 = flags | nonce | mlength}
+@item The authenticated data and plaintext is formatted into the string
+ @code{B = L(adata) | adata | padding | plaintext | padding} with @code{padding}
+ being the shortest string of zero bytes such that the length of the string is
+ a multiple of the block size, and @code{L(adata)} is an encoding of the
+ length of @code{adata}.
+@item The string @code{B} is separated into blocks @code{B_1} ... @code{B_n}
+@item The authentication tag @code{T} is calculated as
+ @code{T=0, for i=0 to n, do T = E_k(B_i XOR T)}
+
+@item An initial counter is then initialized from the nonce to create
+ @code{IC = flags | nonce | padding}, where @code{padding} is the shortest
+ string of zero bytes such that @code{IC} is exactly one block in length.
+@item The authentication tag is encrypted using using @acronym{CTR} mode:
+ @code{MAC = E_k(IC) XOR T}
+@item The plaintext is then encrypted using @acronym{CTR} mode with an initial
+ counter of @code{IC+1}.
+@end itemize
+
+@acronym{CCM} mode decryption operates similarly, except that the ciphertext
+and @acronym{MAC} are first decrypted using CTR mode to retreive the plaintext
+and authentication tag. The authentication tag can then be recalucated from the
+authenticated data and plantext, and compared to the value in the message to
+check for authenticity.
+
+@subsubsection General @acronym{CCM} interface
+
+For all of the functions in the @acronym{CCM} interface, @var{cipher} is the
+context struct for the underlying cipher and @var{f} is the encryption function.
+The cipher's encryption key must be set before calling any of the @acronym{CCM}
+functions. The cipher's decryption function and key are never used.
+
+@deftp {Context struct} {struct ccm_ctx}
+Holds state corresponding to a particular message.
+@end deftp
+
+@defvr Constant CCM_BLOCK_SIZE
+@acronym{CCM}'s block size, 16.
+@end defvr
+
+@deftypefun void ccm_set_nonce (struct ccm_ctx *@var{ctx}, void *@var{cipher}, nettle_crypt_func *@var{f}, size_t @var{noncelen}, const uint8_t *@var{nonce}, size_t @var{authlen}, size_t @var{msglen}, size_t @var{taglen})
+Initializes @var{ctx} using the given nonce and the sizes of the authenticated
+data, message, and @acronym{MAC} to be processed.
+@end deftypefun
+
+@deftypefun void ccm_update (struct ccm_ctx *@var{ctx}, void *@var{cipher}, nettle_crypt_func *@var{f}, size_t @var{length}, const uint8_t *@var{data})
+Provides associated data to be authenticated. Must be called after
+@code{ccm_set_nonce}, and before @code{ccm_encrypt}, @code{ccm_decrypt}, or
+@code{ccm_digest}.
+@end deftypefun
+
+@deftypefun void ccm_encrypt (struct ccm_ctx *@var{ctx}, void *@var{cipher}, nettle_crypt_func *@var{f}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx void ccm_decrypt (struct ccm_ctx *@var{ctx}, void *@var{cipher}, nettle_crypt_func *@var{f}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+Encrypts or decrypts the message data. Must be called after @code{ccm_set_nonce}
+and before @code{ccm_digest}. All but the last call for each message @emph{must}
+use a length that is a multiple of the block size.
+@end deftypefun
+
+@deftypefun void ccm_digest (struct ccm_ctx *@var{ctx}, void *@var{cipher}, nettle_crypt_func *@var{f}, size_t @var{length}, uint8_t *@var{digest})
+Extracts the message digest (also known ``authentication tag''). This is
+the final operation when processing a message. @var{length} is usually
+equal to the @var{taglen} parameter supplied to @code{ccm_set_nonce}, but if you
+provide a smaller value, only the first @var{length} octets of the digest are
+written.
+@end deftypefun
+
+To encrypt a message using the general @acronym{CCM} interface, set the message
+nonce and length using @code{ccm_set_nonce} and then call @code{ccm_update} to
+generate the digest of any authenticated data. After all of the authenticated
+data has been digested use @code{ccm_encrypt} to encrypt the plaintext. Finally,
+use @code{ccm_digest} to return the encrypted @acronym{MAC}.
+
+To decrypt a message, use @code{ccm_set_nonce} and @code{ccm_update} the same as
+you would for encryption, and then call @code{ccm_decrypt} to decrypt the
+ciphertext. After decrypting the ciphertext @code{ccm_digest} will return the
+encrypted @acronym{MAC} which should be identical to the @acronym{MAC} in the
+received message.
+
+@subsubsection @acronym{CCM} message interface
+
+The @acronym{CCM} message fuctions provides a simple interface that will
+perform authentication and message encryption in a single function call. The
+length of the ciphertext is given by @var{clength}, and it is always exactly
+@var{tlength} bytes longer than the corresponding plaintext. The length of the
+plaintext is not provided explicitly in this interface, as it would always have
+a value of @var{mlength} = @var{clength} - @var{tlength}.
+
+@deftypefun void ccm_encrypt_message (void *@var{cipher}, nettle_crypt_func *@var{f}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{tlength}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+Computes the message digest from the @var{adata} and @var{src} parameters,
+encrypts the plaintext from @var{src}, appends the encrypted @acronym{MAC} to
+ciphertext and outputs it to @var{dst}.
+@end deftypefun
+
+@deftypefun int ccm_decrypt_message (void *@var{cipher}, nettle_crypt_func *@var{f}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{tlength}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+Decrypts the ciphertext from @var{src}, outputs the plaintext to @var{dst},
+recalculates the @acronym{MAC} from @var{adata} and the plaintext, and compares
+it to the final @var{tlength} bytes of @var{src}. If the values of the received
+and calculated @acronym{MAC}s are equal, this will return 1 indicating a valid
+and authenticated message. Otherwise, this function will return zero.
+@end deftypefun
+
+@subsubsection @acronym{CCM}-@acronym{AES} interface
+
+The @acronym{AES} @acronym{CCM} functions provide an API for using @acronym{CCM}
+mode with the @acronym{AES} block ciphers. The parameters all have the same
+meaning as the general and message interfaces, except that the @var{cipher},
+@var{f}, and @var{ctx} parameters are replaced with an @acronym{AES} context
+structure, and a set-key function must be called before using any of the other
+functions in this interface.
+@deftp {Context struct} {struct ccm_aes128_ctx}
+Holds state corresponding to a particular message encrypted using the AES-128 block cipher.
+@end deftp
+
+@deftp {Context struct} {struct ccm_aes192_ctx}
+Holds state corresponding to a particular message encrypted using the AES-192 block cipher.
+@end deftp
+
+@deftp {Context struct} {struct ccm_aes256_ctx}
+Holds state corresponding to a particular message encrypted using the AES-256 block cipher.
+@end deftp
+
+@deftypefun void ccm_aes128_set_key (struct ccm_aes128_ctx *@var{ctx}, const void *@var{key})
+@deftypefunx void ccm_aes192_set_key (struct ccm_aes192_ctx *@var{ctx}, const void *@var{key})
+@deftypefunx void ccm_aes256_set_key (struct ccm_aes256_ctx *@var{ctx}, const void *@var{key})
+Initializes the encryption key for the AES block cipher. One of these functions
+must be called before any of the other functions in the @acronym{AES}
+@acronym{CCM} interface.
+@end deftypefun
+
+@deftypefun void ccm_aes128_set_nonce (struct ccm_aes128_ctx *@var{ctx}, size_t @var{noncelen}, const uint8_t *@var{nonce}, size_t @var{authlen}, size_t @var{msglen}, size_t @var{taglen})
+@deftypefunx void ccm_aes192_set_nonce (struct ccm_aes192_ctx *@var{ctx}, size_t @var{noncelen}, const uint8_t *@var{nonce}, size_t @var{authlen}, size_t @var{msglen}, size_t @var{taglen})
+@deftypefunx void ccm_aes256_set_nonce (struct ccm_aes256_ctx *@var{ctx}, size_t @var{noncelen}, const uint8_t *@var{nonce}, size_t @var{authlen}, size_t @var{msglen}, size_t @var{taglen})
+These are identical to @code{ccm_set_nonce}, except that @var{cipher},
+@var{f}, and @var{ctx} are replaced with a context structure.
+@end deftypefun
+
+@deftypefun void ccm_aes128_update (struct ccm_aes128_ctx *@var{ctx}, size_t @var{length}, const uint8_t *@var{data})
+@deftypefunx void ccm_aes192_update (struct ccm_aes192_ctx *@var{ctx}, size_t @var{length}, const uint8_t *@var{data})
+@deftypefunx void ccm_aes256_update (struct ccm_aes256_ctx *@var{ctx}, size_t @var{length}, const uint8_t *@var{data})
+These are identical to @code{ccm_set_update}, except that @var{cipher},
+@var{f}, and @var{ctx} are replaced with a context structure.
+@end deftypefun
+
+@deftypefun void ccm_aes128_encrypt (struct ccm_aes128_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx void ccm_aes192_encrypt (struct ccm_aes192_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx void ccm_aes256_encrypt (struct ccm_aes256_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx void ccm_aes128_decrypt (struct ccm_aes128_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx void ccm_aes192_decrypt (struct ccm_aes192_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx void ccm_aes256_decrypt (struct ccm_aes256_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+These are identical to @code{ccm_set_encrypt} and @code{ccm_set_decrypt}, except
+that @var{cipher}, @var{f}, and @var{ctx} are replaced with a context structure.
+@end deftypefun
+
+@deftypefun void ccm_aes128_digest (struct ccm_aes128_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{digest})
+@deftypefunx void ccm_aes192_digest (struct ccm_aes192_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{digest})
+@deftypefunx void ccm_aes256_digest (struct ccm_aes256_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{digest})
+These are identical to @code{ccm_set_digest}, except that @var{cipher},
+@var{f}, and @var{ctx} are replaced with a context structure.
+@end deftypefun
+
+@deftypefun void ccm_aes128_encrypt_message (struct ccm_aes128_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{tlength}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx void ccm_aes192_encrypt_message (struct ccm_aes192_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{tlength}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx void ccm_aes256_encrypt_message (struct ccm_aes256_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{tlength}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx int ccm_aes128_decrypt_message (struct ccm_aes128_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{tlength}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx int ccm_aes192_decrypt_message (struct ccm_aes192_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{tlength}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx int ccm_aes192_decrypt_message (struct ccm_aes256_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{tlength}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+These are identical to @code{ccm_encrypt_message} and @code{ccm_decrypt_message}
+except that @var{cipher} and @var{f} are replaced with a context structure.
+@end deftypefun
@node Keyed hash functions, Key derivation functions, Cipher modes, Reference
@comment node-name, next, previous, up
--
1.7.9.5