Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  NIST SP800-38C compliant CCM implementation
  3.  *
  4.  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
  5.  *  SPDX-License-Identifier: GPL-2.0
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License along
  18.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  19.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  *  This file is part of mbed TLS (https://tls.mbed.org)
  22.  */
  23.  
  24. /*
  25.  * Definition of CCM:
  26.  * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
  27.  * RFC 3610 "Counter with CBC-MAC (CCM)"
  28.  *
  29.  * Related:
  30.  * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
  31.  */
  32.  
  33. #if !defined(MBEDTLS_CONFIG_FILE)
  34. #include "mbedtls/config.h"
  35. #else
  36. #include MBEDTLS_CONFIG_FILE
  37. #endif
  38.  
  39. #if defined(MBEDTLS_CCM_C)
  40.  
  41. #include "mbedtls/ccm.h"
  42. #include "mbedtls/platform_util.h"
  43.  
  44. #include <string.h>
  45.  
  46. #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
  47. #if defined(MBEDTLS_PLATFORM_C)
  48. #include "mbedtls/platform.h"
  49. #else
  50. #include <stdio.h>
  51. #define mbedtls_printf printf
  52. #endif /* MBEDTLS_PLATFORM_C */
  53. #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
  54.  
  55. #if !defined(MBEDTLS_CCM_ALT)
  56.  
  57. #define CCM_VALIDATE_RET( cond ) \
  58.     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT )
  59. #define CCM_VALIDATE( cond ) \
  60.     MBEDTLS_INTERNAL_VALIDATE( cond )
  61.  
  62. #define CCM_ENCRYPT 0
  63. #define CCM_DECRYPT 1
  64.  
  65. /*
  66.  * Initialize context
  67.  */
  68. void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
  69. {
  70.     CCM_VALIDATE( ctx != NULL );
  71.     memset( ctx, 0, sizeof( mbedtls_ccm_context ) );
  72. }
  73.  
  74. int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
  75.                         mbedtls_cipher_id_t cipher,
  76.                         const unsigned char *key,
  77.                         unsigned int keybits )
  78. {
  79.     int ret;
  80.     const mbedtls_cipher_info_t *cipher_info;
  81.  
  82.     CCM_VALIDATE_RET( ctx != NULL );
  83.     CCM_VALIDATE_RET( key != NULL );
  84.  
  85.     cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
  86.     if( cipher_info == NULL )
  87.         return( MBEDTLS_ERR_CCM_BAD_INPUT );
  88.  
  89.     if( cipher_info->block_size != 16 )
  90.         return( MBEDTLS_ERR_CCM_BAD_INPUT );
  91.  
  92.     mbedtls_cipher_free( &ctx->cipher_ctx );
  93.  
  94.     if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
  95.         return( ret );
  96.  
  97.     if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
  98.                                MBEDTLS_ENCRYPT ) ) != 0 )
  99.     {
  100.         return( ret );
  101.     }
  102.  
  103.     return( 0 );
  104. }
  105.  
  106. /*
  107.  * Free context
  108.  */
  109. void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
  110. {
  111.     if( ctx == NULL )
  112.         return;
  113.     mbedtls_cipher_free( &ctx->cipher_ctx );
  114.     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
  115. }
  116.  
  117. /*
  118.  * Macros for common operations.
  119.  * Results in smaller compiled code than static inline functions.
  120.  */
  121.  
  122. /*
  123.  * Update the CBC-MAC state in y using a block in b
  124.  * (Always using b as the source helps the compiler optimise a bit better.)
  125.  */
  126. #define UPDATE_CBC_MAC                                                      \
  127.     for( i = 0; i < 16; i++ )                                               \
  128.         y[i] ^= b[i];                                                       \
  129.                                                                             \
  130.     if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
  131.         return( ret );
  132.  
  133. /*
  134.  * Encrypt or decrypt a partial block with CTR
  135.  * Warning: using b for temporary storage! src and dst must not be b!
  136.  * This avoids allocating one more 16 bytes buffer while allowing src == dst.
  137.  */
  138. #define CTR_CRYPT( dst, src, len  )                                            \
  139.     do                                                                  \
  140.     {                                                                   \
  141.         if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr,       \
  142.                                            16, b, &olen ) ) != 0 )      \
  143.         {                                                               \
  144.             return( ret );                                              \
  145.         }                                                               \
  146.                                                                         \
  147.         for( i = 0; i < (len); i++ )                                    \
  148.             (dst)[i] = (src)[i] ^ b[i];                                 \
  149.     } while( 0 )
  150.  
  151. /*
  152.  * Authenticated encryption or decryption
  153.  */
  154. static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
  155.                            const unsigned char *iv, size_t iv_len,
  156.                            const unsigned char *add, size_t add_len,
  157.                            const unsigned char *input, unsigned char *output,
  158.                            unsigned char *tag, size_t tag_len )
  159. {
  160.     int ret;
  161.     unsigned char i;
  162.     unsigned char q;
  163.     size_t len_left, olen;
  164.     unsigned char b[16];
  165.     unsigned char y[16];
  166.     unsigned char ctr[16];
  167.     const unsigned char *src;
  168.     unsigned char *dst;
  169.  
  170.     /*
  171.      * Check length requirements: SP800-38C A.1
  172.      * Additional requirement: a < 2^16 - 2^8 to simplify the code.
  173.      * 'length' checked later (when writing it to the first block)
  174.      *
  175.      * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
  176.      */
  177.     if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
  178.         return( MBEDTLS_ERR_CCM_BAD_INPUT );
  179.  
  180.     /* Also implies q is within bounds */
  181.     if( iv_len < 7 || iv_len > 13 )
  182.         return( MBEDTLS_ERR_CCM_BAD_INPUT );
  183.  
  184.     if( add_len > 0xFF00 )
  185.         return( MBEDTLS_ERR_CCM_BAD_INPUT );
  186.  
  187.     q = 16 - 1 - (unsigned char) iv_len;
  188.  
  189.     /*
  190.      * First block B_0:
  191.      * 0        .. 0        flags
  192.      * 1        .. iv_len   nonce (aka iv)
  193.      * iv_len+1 .. 15       length
  194.      *
  195.      * With flags as (bits):
  196.      * 7        0
  197.      * 6        add present?
  198.      * 5 .. 3   (t - 2) / 2
  199.      * 2 .. 0   q - 1
  200.      */
  201.     b[0] = 0;
  202.     b[0] |= ( add_len > 0 ) << 6;
  203.     b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
  204.     b[0] |= q - 1;
  205.  
  206.     memcpy( b + 1, iv, iv_len );
  207.  
  208.     for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
  209.         b[15-i] = (unsigned char)( len_left & 0xFF );
  210.  
  211.     if( len_left > 0 )
  212.         return( MBEDTLS_ERR_CCM_BAD_INPUT );
  213.  
  214.  
  215.     /* Start CBC-MAC with first block */
  216.     memset( y, 0, 16 );
  217.     UPDATE_CBC_MAC;
  218.  
  219.     /*
  220.      * If there is additional data, update CBC-MAC with
  221.      * add_len, add, 0 (padding to a block boundary)
  222.      */
  223.     if( add_len > 0 )
  224.     {
  225.         size_t use_len;
  226.         len_left = add_len;
  227.         src = add;
  228.  
  229.         memset( b, 0, 16 );
  230.         b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
  231.         b[1] = (unsigned char)( ( add_len      ) & 0xFF );
  232.  
  233.         use_len = len_left < 16 - 2 ? len_left : 16 - 2;
  234.         memcpy( b + 2, src, use_len );
  235.         len_left -= use_len;
  236.         src += use_len;
  237.  
  238.         UPDATE_CBC_MAC;
  239.  
  240.         while( len_left > 0 )
  241.         {
  242.             use_len = len_left > 16 ? 16 : len_left;
  243.  
  244.             memset( b, 0, 16 );
  245.             memcpy( b, src, use_len );
  246.             UPDATE_CBC_MAC;
  247.  
  248.             len_left -= use_len;
  249.             src += use_len;
  250.         }
  251.     }
  252.  
  253.     /*
  254.      * Prepare counter block for encryption:
  255.      * 0        .. 0        flags
  256.      * 1        .. iv_len   nonce (aka iv)
  257.      * iv_len+1 .. 15       counter (initially 1)
  258.      *
  259.      * With flags as (bits):
  260.      * 7 .. 3   0
  261.      * 2 .. 0   q - 1
  262.      */
  263.     ctr[0] = q - 1;
  264.     memcpy( ctr + 1, iv, iv_len );
  265.     memset( ctr + 1 + iv_len, 0, q );
  266.     ctr[15] = 1;
  267.  
  268.     /*
  269.      * Authenticate and {en,de}crypt the message.
  270.      *
  271.      * The only difference between encryption and decryption is
  272.      * the respective order of authentication and {en,de}cryption.
  273.      */
  274.     len_left = length;
  275.     src = input;
  276.     dst = output;
  277.  
  278.     while( len_left > 0 )
  279.     {
  280.         size_t use_len = len_left > 16 ? 16 : len_left;
  281.  
  282.         if( mode == CCM_ENCRYPT )
  283.         {
  284.             memset( b, 0, 16 );
  285.             memcpy( b, src, use_len );
  286.             UPDATE_CBC_MAC;
  287.         }
  288.  
  289.         CTR_CRYPT( dst, src, use_len );
  290.  
  291.         if( mode == CCM_DECRYPT )
  292.         {
  293.             memset( b, 0, 16 );
  294.             memcpy( b, dst, use_len );
  295.             UPDATE_CBC_MAC;
  296.         }
  297.  
  298.         dst += use_len;
  299.         src += use_len;
  300.         len_left -= use_len;
  301.  
  302.         /*
  303.          * Increment counter.
  304.          * No need to check for overflow thanks to the length check above.
  305.          */
  306.         for( i = 0; i < q; i++ )
  307.             if( ++ctr[15-i] != 0 )
  308.                 break;
  309.     }
  310.  
  311.     /*
  312.      * Authentication: reset counter and crypt/mask internal tag
  313.      */
  314.     for( i = 0; i < q; i++ )
  315.         ctr[15-i] = 0;
  316.  
  317.     CTR_CRYPT( y, y, 16 );
  318.     memcpy( tag, y, tag_len );
  319.  
  320.     return( 0 );
  321. }
  322.  
  323. /*
  324.  * Authenticated encryption
  325.  */
  326. int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
  327.                          const unsigned char *iv, size_t iv_len,
  328.                          const unsigned char *add, size_t add_len,
  329.                          const unsigned char *input, unsigned char *output,
  330.                          unsigned char *tag, size_t tag_len )
  331. {
  332.     CCM_VALIDATE_RET( ctx != NULL );
  333.     CCM_VALIDATE_RET( iv != NULL );
  334.     CCM_VALIDATE_RET( add_len == 0 || add != NULL );
  335.     CCM_VALIDATE_RET( length == 0 || input != NULL );
  336.     CCM_VALIDATE_RET( length == 0 || output != NULL );
  337.     CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
  338.     return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
  339.                             add, add_len, input, output, tag, tag_len ) );
  340. }
  341.  
  342. int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
  343.                          const unsigned char *iv, size_t iv_len,
  344.                          const unsigned char *add, size_t add_len,
  345.                          const unsigned char *input, unsigned char *output,
  346.                          unsigned char *tag, size_t tag_len )
  347. {
  348.     CCM_VALIDATE_RET( ctx != NULL );
  349.     CCM_VALIDATE_RET( iv != NULL );
  350.     CCM_VALIDATE_RET( add_len == 0 || add != NULL );
  351.     CCM_VALIDATE_RET( length == 0 || input != NULL );
  352.     CCM_VALIDATE_RET( length == 0 || output != NULL );
  353.     CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
  354.     if( tag_len == 0 )
  355.         return( MBEDTLS_ERR_CCM_BAD_INPUT );
  356.  
  357.     return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
  358.                 add_len, input, output, tag, tag_len ) );
  359. }
  360.  
  361. /*
  362.  * Authenticated decryption
  363.  */
  364. int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
  365.                       const unsigned char *iv, size_t iv_len,
  366.                       const unsigned char *add, size_t add_len,
  367.                       const unsigned char *input, unsigned char *output,
  368.                       const unsigned char *tag, size_t tag_len )
  369. {
  370.     int ret;
  371.     unsigned char check_tag[16];
  372.     unsigned char i;
  373.     int diff;
  374.  
  375.     CCM_VALIDATE_RET( ctx != NULL );
  376.     CCM_VALIDATE_RET( iv != NULL );
  377.     CCM_VALIDATE_RET( add_len == 0 || add != NULL );
  378.     CCM_VALIDATE_RET( length == 0 || input != NULL );
  379.     CCM_VALIDATE_RET( length == 0 || output != NULL );
  380.     CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
  381.  
  382.     if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
  383.                                 iv, iv_len, add, add_len,
  384.                                 input, output, check_tag, tag_len ) ) != 0 )
  385.     {
  386.         return( ret );
  387.     }
  388.  
  389.     /* Check tag in "constant-time" */
  390.     for( diff = 0, i = 0; i < tag_len; i++ )
  391.         diff |= tag[i] ^ check_tag[i];
  392.  
  393.     if( diff != 0 )
  394.     {
  395.         mbedtls_platform_zeroize( output, length );
  396.         return( MBEDTLS_ERR_CCM_AUTH_FAILED );
  397.     }
  398.  
  399.     return( 0 );
  400. }
  401.  
  402. int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
  403.                       const unsigned char *iv, size_t iv_len,
  404.                       const unsigned char *add, size_t add_len,
  405.                       const unsigned char *input, unsigned char *output,
  406.                       const unsigned char *tag, size_t tag_len )
  407. {
  408.     CCM_VALIDATE_RET( ctx != NULL );
  409.     CCM_VALIDATE_RET( iv != NULL );
  410.     CCM_VALIDATE_RET( add_len == 0 || add != NULL );
  411.     CCM_VALIDATE_RET( length == 0 || input != NULL );
  412.     CCM_VALIDATE_RET( length == 0 || output != NULL );
  413.     CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
  414.  
  415.     if( tag_len == 0 )
  416.         return( MBEDTLS_ERR_CCM_BAD_INPUT );
  417.  
  418.     return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
  419.                 add_len, input, output, tag, tag_len ) );
  420. }
  421. #endif /* !MBEDTLS_CCM_ALT */
  422.  
  423. #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
  424. /*
  425.  * Examples 1 to 3 from SP800-38C Appendix C
  426.  */
  427.  
  428. #define NB_TESTS 3
  429. #define CCM_SELFTEST_PT_MAX_LEN 24
  430. #define CCM_SELFTEST_CT_MAX_LEN 32
  431. /*
  432.  * The data is the same for all tests, only the used length changes
  433.  */
  434. static const unsigned char key[] = {
  435.     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
  436.     0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
  437. };
  438.  
  439. static const unsigned char iv[] = {
  440.     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  441.     0x18, 0x19, 0x1a, 0x1b
  442. };
  443.  
  444. static const unsigned char ad[] = {
  445.     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  446.     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  447.     0x10, 0x11, 0x12, 0x13
  448. };
  449.  
  450. static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = {
  451.     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
  452.     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  453.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  454. };
  455.  
  456. static const size_t iv_len [NB_TESTS] = { 7, 8,  12 };
  457. static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
  458. static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
  459. static const size_t tag_len[NB_TESTS] = { 4, 6,  8  };
  460.  
  461. static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
  462.     {   0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
  463.     {   0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
  464.         0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
  465.         0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
  466.     {   0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
  467.         0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
  468.         0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
  469.         0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
  470. };
  471.  
  472. int mbedtls_ccm_self_test( int verbose )
  473. {
  474.     mbedtls_ccm_context ctx;
  475.     /*
  476.      * Some hardware accelerators require the input and output buffers
  477.      * would be in RAM, because the flash is not accessible.
  478.      * Use buffers on the stack to hold the test vectors data.
  479.      */
  480.     unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
  481.     unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
  482.     size_t i;
  483.     int ret;
  484.  
  485.     mbedtls_ccm_init( &ctx );
  486.  
  487.     if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
  488.     {
  489.         if( verbose != 0 )
  490.             mbedtls_printf( "  CCM: setup failed" );
  491.  
  492.         return( 1 );
  493.     }
  494.  
  495.     for( i = 0; i < NB_TESTS; i++ )
  496.     {
  497.         if( verbose != 0 )
  498.             mbedtls_printf( "  CCM-AES #%u: ", (unsigned int) i + 1 );
  499.  
  500.         memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
  501.         memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN );
  502.         memcpy( plaintext, msg, msg_len[i] );
  503.  
  504.         ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
  505.                                            iv, iv_len[i], ad, add_len[i],
  506.                                            plaintext, ciphertext,
  507.                                            ciphertext + msg_len[i], tag_len[i] );
  508.  
  509.         if( ret != 0 ||
  510.             memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 )
  511.         {
  512.             if( verbose != 0 )
  513.                 mbedtls_printf( "failed\n" );
  514.  
  515.             return( 1 );
  516.         }
  517.         memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
  518.  
  519.         ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
  520.                                         iv, iv_len[i], ad, add_len[i],
  521.                                         ciphertext, plaintext,
  522.                                         ciphertext + msg_len[i], tag_len[i] );
  523.  
  524.         if( ret != 0 ||
  525.             memcmp( plaintext, msg, msg_len[i] ) != 0 )
  526.         {
  527.             if( verbose != 0 )
  528.                 mbedtls_printf( "failed\n" );
  529.  
  530.             return( 1 );
  531.         }
  532.  
  533.         if( verbose != 0 )
  534.             mbedtls_printf( "passed\n" );
  535.     }
  536.  
  537.     mbedtls_ccm_free( &ctx );
  538.  
  539.     if( verbose != 0 )
  540.         mbedtls_printf( "\n" );
  541.  
  542.     return( 0 );
  543. }
  544.  
  545. #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
  546.  
  547. #endif /* MBEDTLS_CCM_C */
  548.