diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index c8fdd2567..59015929b 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -659,6 +659,71 @@ int cipher_crypt( cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ); +#if defined(POLARSSL_CIPHER_MODE_AEAD) +/** + * \brief Generic autenticated encryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to authenticate. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer for the authentication tag + * \param tag_len desired tag length + * + * \returns 0 on success, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or + * a cipher specific error code. + */ +int cipher_auth_encrypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); + +/** + * \brief Generic autenticated decryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to be authenticated. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer holding the authentication tag + * \param tag_len length of the authentication tag + * + * \returns 0 on success, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or + * POLARSSL_ERR_CIPHER_AUTH_FAILED if data isn't authentic, + * or a cipher specific error code. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext to + * be used by mistake, making this interface safer. + */ +int cipher_auth_decrypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ + /** * \brief Checkup routine * diff --git a/library/cipher.c b/library/cipher.c index daeea1376..d8b416ad7 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -799,6 +799,62 @@ int cipher_crypt( cipher_context_t *ctx, return( 0 ); } +#if defined(POLARSSL_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes + */ +int cipher_auth_encrypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ +#if defined(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( gcm_crypt_and_tag( ctx->cipher_ctx, GCM_ENCRYPT, ilen, + iv, iv_len, ad, ad_len, input, output, + tag_len, tag ) ); + } +#endif + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented decryption for AEAD modes + */ +int cipher_auth_decrypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ +#if defined(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == POLARSSL_ERR_GCM_AUTH_FAILED ) + ret = POLARSSL_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* POLARSSL_CIPHER_MODE_AEAD */ + + #if defined(POLARSSL_SELF_TEST) /*