1238384Sjkim/********************************************************************** 2238384Sjkim * keywrap.c * 3238384Sjkim * Copyright (c) 2005-2006 Cryptocom LTD * 4238384Sjkim * This file is distributed under the same license as OpenSSL * 5238384Sjkim * * 6238384Sjkim * Implementation of CryptoPro key wrap algorithm, as defined in * 7238384Sjkim * RFC 4357 p 6.3 and 6.4 * 8238384Sjkim * Doesn't need OpenSSL * 9238384Sjkim **********************************************************************/ 10238384Sjkim#include <string.h> 11238384Sjkim#include "gost89.h" 12238384Sjkim#include "gost_keywrap.h" 13238384Sjkim 14280304Sjkim/*- 15280304Sjkim * Diversifies key using random UserKey Material 16280304Sjkim * Implements RFC 4357 p 6.5 key diversification algorithm 17280304Sjkim * 18238384Sjkim * inputKey - 32byte key to be diversified 19238384Sjkim * ukm - 8byte user key material 20280304Sjkim * outputKey - 32byte buffer to store diversified key 21238384Sjkim * 22238384Sjkim */ 23280304Sjkimvoid keyDiversifyCryptoPro(gost_ctx * ctx, const unsigned char *inputKey, 24280304Sjkim const unsigned char *ukm, unsigned char *outputKey) 25280304Sjkim{ 26238384Sjkim 27280304Sjkim u4 k, s1, s2; 28280304Sjkim int i, j, mask; 29280304Sjkim unsigned char S[8]; 30280304Sjkim memcpy(outputKey, inputKey, 32); 31280304Sjkim for (i = 0; i < 8; i++) { 32280304Sjkim /* Make array of integers from key */ 33280304Sjkim /* Compute IV S */ 34280304Sjkim s1 = 0, s2 = 0; 35280304Sjkim for (j = 0, mask = 1; j < 8; j++, mask <<= 1) { 36280304Sjkim k = ((u4) outputKey[4 * j]) | (outputKey[4 * j + 1] << 8) | 37280304Sjkim (outputKey[4 * j + 2] << 16) | (outputKey[4 * j + 3] << 24); 38280304Sjkim if (mask & ukm[i]) { 39280304Sjkim s1 += k; 40280304Sjkim } else { 41280304Sjkim s2 += k; 42280304Sjkim } 43280304Sjkim } 44280304Sjkim S[0] = (unsigned char)(s1 & 0xff); 45280304Sjkim S[1] = (unsigned char)((s1 >> 8) & 0xff); 46280304Sjkim S[2] = (unsigned char)((s1 >> 16) & 0xff); 47280304Sjkim S[3] = (unsigned char)((s1 >> 24) & 0xff); 48280304Sjkim S[4] = (unsigned char)(s2 & 0xff); 49280304Sjkim S[5] = (unsigned char)((s2 >> 8) & 0xff); 50280304Sjkim S[6] = (unsigned char)((s2 >> 16) & 0xff); 51280304Sjkim S[7] = (unsigned char)((s2 >> 24) & 0xff); 52280304Sjkim gost_key(ctx, outputKey); 53280304Sjkim gost_enc_cfb(ctx, S, outputKey, outputKey, 4); 54280304Sjkim } 55280304Sjkim} 56238384Sjkim 57280304Sjkim/*- 58238384Sjkim * Wraps key using RFC 4357 6.3 59280304Sjkim * ctx - gost encryption context, initialized with some S-boxes 60238384Sjkim * keyExchangeKey (KEK) 32-byte (256-bit) shared key 61280304Sjkim * ukm - 8 byte (64 bit) user key material, 62238384Sjkim * sessionKey - 32-byte (256-bit) key to be wrapped 63238384Sjkim * wrappedKey - 44-byte buffer to store wrapped key 64280304Sjkim */ 65238384Sjkim 66280304Sjkimint keyWrapCryptoPro(gost_ctx * ctx, const unsigned char *keyExchangeKey, 67280304Sjkim const unsigned char *ukm, 68280304Sjkim const unsigned char *sessionKey, 69280304Sjkim unsigned char *wrappedKey) 70280304Sjkim{ 71280304Sjkim unsigned char kek_ukm[32]; 72280304Sjkim keyDiversifyCryptoPro(ctx, keyExchangeKey, ukm, kek_ukm); 73280304Sjkim gost_key(ctx, kek_ukm); 74280304Sjkim memcpy(wrappedKey, ukm, 8); 75280304Sjkim gost_enc(ctx, sessionKey, wrappedKey + 8, 4); 76280304Sjkim gost_mac_iv(ctx, 32, ukm, sessionKey, 32, wrappedKey + 40); 77280304Sjkim return 1; 78280304Sjkim} 79280304Sjkim 80280304Sjkim/*- 81238384Sjkim * Unwraps key using RFC 4357 6.4 82280304Sjkim * ctx - gost encryption context, initialized with some S-boxes 83238384Sjkim * keyExchangeKey 32-byte shared key 84238384Sjkim * wrappedKey 44 byte key to be unwrapped (concatenation of 8-byte UKM, 85280304Sjkim * 32 byte encrypted key and 4 byte MAC 86280304Sjkim * 87238384Sjkim * sessionKEy - 32byte buffer to store sessionKey in 88238384Sjkim * Returns 1 if key is decrypted successfully, and 0 if MAC doesn't match 89280304Sjkim */ 90238384Sjkim 91280304Sjkimint keyUnwrapCryptoPro(gost_ctx * ctx, const unsigned char *keyExchangeKey, 92280304Sjkim const unsigned char *wrappedKey, 93280304Sjkim unsigned char *sessionKey) 94280304Sjkim{ 95280304Sjkim unsigned char kek_ukm[32], cek_mac[4]; 96280304Sjkim keyDiversifyCryptoPro(ctx, keyExchangeKey, wrappedKey 97280304Sjkim /* First 8 bytes of wrapped Key is ukm */ 98280304Sjkim , kek_ukm); 99280304Sjkim gost_key(ctx, kek_ukm); 100280304Sjkim gost_dec(ctx, wrappedKey + 8, sessionKey, 4); 101280304Sjkim gost_mac_iv(ctx, 32, wrappedKey, sessionKey, 32, cek_mac); 102280304Sjkim if (memcmp(cek_mac, wrappedKey + 40, 4)) { 103280304Sjkim return 0; 104280304Sjkim } 105280304Sjkim return 1; 106280304Sjkim} 107