/* * 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); }
static void sm4_setkey( unsigned int SK[32], unsigned char key[16] ) { unsigned int MK[4]; unsigned int k[36]; unsigned int i = 0; GET_UINT32_BE( MK[0], key, 0 ); GET_UINT32_BE( MK[1], key, 4 ); GET_UINT32_BE( MK[2], key, 8 ); GET_UINT32_BE( MK[3], key, 12 ); k[0] = MK[0]^FK[0]; k[1] = MK[1]^FK[1]; k[2] = MK[2]^FK[2]; k[3] = MK[3]^FK[3]; for(; i<32; i++) { k[i+4] = k[i] ^ (sm4CalciRK(k[i+1]^k[i+2]^k[i+3]^CK[i])); SK[i] = k[i+4]; } }
/* 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-AD as defined in SP 800-38F section 6.2 * KWP-AD as defined in SP 800-38F section 6.3 */ int mbedtls_nist_kw_unwrap( 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 i, olen; unsigned char A[KW_SEMIBLOCK_LENGTH]; unsigned char diff, bad_padding = 0; *out_len = 0; if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } if( mode == MBEDTLS_KW_MODE_KW ) { /* * According to SP 800-38F Table 1, the ciphertext length for KW * must be between 3 to 2^54 semiblocks inclusive. */ if( in_len < 24 || #if SIZE_MAX > 0x200000000000000 in_len > 0x200000000000000 || #endif in_len % KW_SEMIBLOCK_LENGTH != 0 ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, A, output, out_len ); if( ret != 0 ) goto cleanup; /* Check ICV in "constant-time" */ diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); if( diff != 0 ) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; goto cleanup; } } else if( mode == MBEDTLS_KW_MODE_KWP ) { size_t padlen = 0; uint32_t Plen; /* * According to SP 800-38F Table 1, the ciphertext length for KWP * must be between 2 to 2^29 semiblocks inclusive. */ if( in_len < KW_SEMIBLOCK_LENGTH * 2 || #if SIZE_MAX > 0x100000000 in_len > 0x100000000 || #endif in_len % KW_SEMIBLOCK_LENGTH != 0 ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) { unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; ret = mbedtls_cipher_update( &ctx->cipher_ctx, input, 16, outbuff, &olen ); if( ret != 0 ) goto cleanup; memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); *out_len = KW_SEMIBLOCK_LENGTH; } else { /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, A, output, out_len ); if( ret != 0 ) goto cleanup; } /* Check ICV in "constant-time" */ diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); if( diff != 0 ) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 ); /* * Plen is the length of the plaintext, when the input is valid. * If Plen is larger than the plaintext and padding, padlen will be * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; if ( padlen > 7 ) { padlen &= 7; ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } /* Check padding in "constant-time" */ for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) { if( i >= KW_SEMIBLOCK_LENGTH - padlen ) diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; else bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; } if( diff != 0 ) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } if( ret != 0 ) { goto cleanup; } memset( output + Plen, 0, padlen ); *out_len = Plen; } else { ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; goto cleanup; } cleanup: if( ret != 0 ) { memset( output, 0, *out_len ); *out_len = 0; } mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); mbedtls_platform_zeroize( &diff, sizeof( diff ) ); mbedtls_platform_zeroize( A, sizeof( A ) ); return( ret ); }