/* * SM4 standard one round processing * */ static void sm4_one_round( unsigned int sk[32], unsigned char input[16], unsigned char output[16] ) { unsigned int i = 0; unsigned int ulbuf[36]; memset(ulbuf, 0, sizeof(ulbuf)); GET_UINT32_BE( ulbuf[0], input, 0 ) GET_UINT32_BE( ulbuf[1], input, 4 ) GET_UINT32_BE( ulbuf[2], input, 8 ) GET_UINT32_BE( ulbuf[3], input, 12 ) while(i<32) { ulbuf[i+4] = sm4F(ulbuf[i], ulbuf[i+1], ulbuf[i+2], ulbuf[i+3], sk[i]); // #ifdef _DEBUG // printf("rk(%02d) = 0x%08x, X(%02d) = 0x%08x \n",i,sk[i], i, ulbuf[i+4] ); // #endif i++; } PUT_UINT32_BE(ulbuf[35],output,0); PUT_UINT32_BE(ulbuf[34],output,4); PUT_UINT32_BE(ulbuf[33],output,8); PUT_UINT32_BE(ulbuf[32],output,12); }
void sha256(unsigned char input[32], int rounds, unsigned char output[32]) { GET_UINT32_BE( W[0], input, 0 ); GET_UINT32_BE( W[1], input, 4 ); GET_UINT32_BE( W[2], input, 8 ); GET_UINT32_BE( W[3], input, 12 ); GET_UINT32_BE( W[4], input, 16 ); GET_UINT32_BE( W[5], input, 20 ); GET_UINT32_BE( W[6], input, 24 ); GET_UINT32_BE( W[7], input, 28 ); int i; for(i=0;i<rounds;++i) sha256_transform(); PUT_UINT32_BE( W[0], output, 0 ); PUT_UINT32_BE( W[1], output, 4 ); PUT_UINT32_BE( W[2], output, 8 ); PUT_UINT32_BE( W[3], output, 12 ); PUT_UINT32_BE( W[4], output, 16 ); PUT_UINT32_BE( W[5], output, 20 ); PUT_UINT32_BE( W[6], output, 24 ); PUT_UINT32_BE( W[7], output, 28 ); }
/* * Blowfish-ECB block encryption/decryption */ int mbedtls_blowfish_crypt_ecb(mbedtls_blowfish_context *ctx, int mode, const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE]) { uint32_t X0, X1; GET_UINT32_BE(X0, input, 0); GET_UINT32_BE(X1, input, 4); if (mode == MBEDTLS_BLOWFISH_DECRYPT) { blowfish_dec(ctx, &X0, &X1); } else { /* MBEDTLS_BLOWFISH_ENCRYPT */ blowfish_enc(ctx, &X0, &X1); } PUT_UINT32_BE(X0, output, 0); PUT_UINT32_BE(X1, output, 4); return (0); }
/* private function: * Calculating round encryption key. * args: [in] a: a is a 32 bits unsigned value; * return: sk[i]: i{0,1,2,3,...31}. */ static unsigned int sm4CalciRK(unsigned int ka) { unsigned int bb = 0; unsigned int rk = 0; unsigned char a[4]; unsigned char b[4]; PUT_UINT32_BE(ka,a,0) b[0] = sm4Sbox(a[0]); b[1] = sm4Sbox(a[1]); b[2] = sm4Sbox(a[2]); b[3] = sm4Sbox(a[3]); GET_UINT32_BE(bb,b,0) rk = bb^(ROTL(bb, 13))^(ROTL(bb, 23)); return rk; }
/* * private F(Lt) function: * "T algorithm" == "L algorithm" + "t algorithm". * args: [in] a: a is a 32 bits unsigned value; * return: c: c is calculated with line algorithm "L" and nonline algorithm "t" */ static unsigned int sm4Lt(unsigned int ka) { unsigned int bb = 0; unsigned int c = 0; unsigned char a[4]; unsigned char b[4]; PUT_UINT32_BE(ka,a,0) b[0] = sm4Sbox(a[0]); b[1] = sm4Sbox(a[1]); b[2] = sm4Sbox(a[2]); b[3] = sm4Sbox(a[3]); GET_UINT32_BE(bb,b,0) c =bb^(ROTL(bb, 2))^(ROTL(bb, 10))^(ROTL(bb, 18))^(ROTL(bb, 24)); return c; }
/* * KW-AE as defined in SP 800-38F section 6.2 * KWP-AE as defined in SP 800-38F section 6.3 */ int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, const unsigned char *input, size_t in_len, unsigned char *output, size_t *out_len, size_t out_size ) { int ret = 0; size_t semiblocks = 0; size_t s; size_t olen, padlen = 0; uint64_t t = 0; unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; unsigned char *A = output; *out_len = 0; /* * Generate the String to work on */ if( mode == MBEDTLS_KW_MODE_KW ) { if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } /* * According to SP 800-38F Table 1, the plaintext length for KW * must be between 2 to 2^54-1 semiblocks inclusive. */ if( in_len < 16 || #if SIZE_MAX > 0x1FFFFFFFFFFFFF8 in_len > 0x1FFFFFFFFFFFFF8 || #endif in_len % KW_SEMIBLOCK_LENGTH != 0 ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); } else { if( in_len % 8 != 0 ) { padlen = ( 8 - ( in_len % 8 ) ); } if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } /* * According to SP 800-38F Table 1, the plaintext length for KWP * must be between 1 and 2^32-1 octets inclusive. */ if( in_len < 1 #if SIZE_MAX > 0xFFFFFFFF || in_len > 0xFFFFFFFF #endif ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); PUT_UINT32_BE( ( in_len & 0xffffffff ), output, KW_SEMIBLOCK_LENGTH / 2 ); memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); } semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; s = 6 * ( semiblocks - 1 ); if( mode == MBEDTLS_KW_MODE_KWP && in_len <= KW_SEMIBLOCK_LENGTH ) { memcpy( inbuff, output, 16 ); ret = mbedtls_cipher_update( &ctx->cipher_ctx, inbuff, 16, output, &olen ); if( ret != 0 ) goto cleanup; } else { /* * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 */ if( semiblocks < MIN_SEMIBLOCKS_COUNT ) { ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; goto cleanup; } /* Calculate intermediate values */ for( t = 1; t <= s; t++ ) { memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); ret = mbedtls_cipher_update( &ctx->cipher_ctx, inbuff, 16, outbuff, &olen ); if( ret != 0 ) goto cleanup; memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); calc_a_xor_t( A, t ); memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); R2 += KW_SEMIBLOCK_LENGTH; if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) R2 = output + KW_SEMIBLOCK_LENGTH; } } *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; cleanup: if( ret != 0) { memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); } mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); return( ret ); }