1 /*
2  * SRT - Secure, Reliable, Transport
3  * Copyright (c) 2019 Haivision Systems Inc.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  */
10 
11 
12 /*****************************************************************************
13 written by
14    Haivision Systems Inc.
15 
16    2019-06-28 (jdube)
17         CRYSPR/4SRT Initial implementation.
18 *****************************************************************************/
19 
20 #include "hcrypt.h"
21 #include "cryspr.h"
22 
23 #include <stdlib.h>
24 #include <string.h>
25 
crysprStub_Prng(unsigned char * rn,int len)26 int crysprStub_Prng(unsigned char *rn, int len)
27 {
28     (void)rn;
29     (void)len;
30     return(0);
31 }
32 
crysprStub_AES_SetKey(bool bEncrypt,const unsigned char * kstr,size_t kstr_len,CRYSPR_AESCTX * aes_key)33 int crysprStub_AES_SetKey(
34     bool bEncrypt,              /* true Enxcrypt key, false: decrypt */
35     const unsigned char *kstr,  /* key sttring*/
36     size_t kstr_len,            /* kstr len in  bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
37     CRYSPR_AESCTX *aes_key)     /* Cryptolib Specific AES key context */
38 {
39     (void)bEncrypt;
40     (void)kstr;
41     (void)kstr_len;
42     (void)aes_key;
43 
44     return(0);
45 }
46 
crysprStub_AES_EcbCipher(bool bEncrypt,CRYSPR_AESCTX * aes_key,const unsigned char * indata,size_t inlen,unsigned char * out_txt,size_t * outlen)47 int crysprStub_AES_EcbCipher(
48     bool bEncrypt,              /* true:encrypt, false:decrypt */
49     CRYSPR_AESCTX *aes_key,     /* AES context */
50     const unsigned char *indata,/* src (clear text)*/
51     size_t inlen,               /* length */
52     unsigned char *out_txt,     /* dst (cipher text) */
53     size_t *outlen)             /* dst len */
54 {
55     (void)bEncrypt;
56     (void)aes_key;
57     (void)indata;
58     (void)inlen;
59     (void)out_txt;
60     (void)outlen;
61 
62     return -1;
63 }
64 
crysprStub_AES_CtrCipher(bool bEncrypt,CRYSPR_AESCTX * aes_key,unsigned char * iv,const unsigned char * indata,size_t inlen,unsigned char * out_txt)65 int crysprStub_AES_CtrCipher(
66     bool bEncrypt,              /* true:encrypt, false:decrypt */
67     CRYSPR_AESCTX *aes_key,     /* AES context */
68     unsigned char *iv,          /* iv */
69     const unsigned char *indata,/* src */
70     size_t inlen,               /* length */
71     unsigned char *out_txt)     /* dest */
72 {
73     (void)bEncrypt;
74     (void)aes_key;
75     (void)iv;
76     (void)indata;
77     (void)inlen;
78     (void)out_txt;
79 
80     return(-1);
81 }
82 
crysprStub_SHA1_MsgDigest(const unsigned char * m,size_t m_len,unsigned char * md)83 unsigned char *crysprStub_SHA1_MsgDigest(
84     const unsigned char *m, /* in: message */
85     size_t m_len,           /* message length */
86     unsigned char *md)      /* out: message digest buffer *160 bytes */
87 {
88     (void)m;
89     (void)m_len;
90     (void)md;
91 
92     return(NULL);//return md;
93 }
94 
95 /*
96 * Password-based Key Derivation Function
97 */
crysprStub_KmPbkdf2(CRYSPR_cb * cryspr_cb,char * passwd,size_t passwd_len,unsigned char * salt,size_t salt_len,int itr,size_t key_len,unsigned char * out)98 int crysprStub_KmPbkdf2(
99     CRYSPR_cb *cryspr_cb,
100     char *passwd,           /* passphrase */
101     size_t passwd_len,      /* passphrase len */
102     unsigned char *salt,    /* salt */
103     size_t salt_len,        /* salt_len */
104     int itr,                /* iterations */
105     size_t key_len,         /* key_len */
106     unsigned char *out)     /* derived key */
107 {
108     (void)cryspr_cb;
109     (void)passwd;
110     (void)passwd_len;
111     (void)salt;
112     (void)salt_len;
113     (void)itr;
114     (void)key_len;
115     (void)out;
116 
117     /* >>Todo:
118      * develop PBKDF2 using SHA1 primitive cryspr_cb->cryspr->sha1_msg_digest() for cryptolibs not providing it
119      */
120     return(-1);
121 }
122 
crysprFallback_KmSetKey(CRYSPR_cb * cryspr_cb,bool bWrap,const unsigned char * kek,size_t kek_len)123 static int crysprFallback_KmSetKey(CRYSPR_cb *cryspr_cb, bool bWrap, const unsigned char *kek, size_t kek_len)
124 {
125 	CRYSPR_AESCTX *aes_kek = &cryspr_cb->aes_kek;
126 
127     if (cryspr_cb->cryspr->aes_set_key(bWrap, kek, kek_len, aes_kek)) {
128         HCRYPT_LOG(LOG_ERR, "AES_set_%s_key(kek) failed\n", bWrap? "encrypt": "decrypt");
129         return(-1);
130     }
131 	return(0);
132 }
133 
134 /*
135 * AES_wrap_key()/AES_unwrap_key() introduced in openssl 0.9.8h
136 * Here is an implementation using AES native API for cryspr not providing it.
137 */
138 
139 static const unsigned char default_iv[] = {
140   0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
141 };
crysprFallback_AES_WrapKey(CRYSPR_cb * cryspr_cb,unsigned char * out,const unsigned char * in,unsigned int inlen)142 int crysprFallback_AES_WrapKey(CRYSPR_cb *cryspr_cb,
143 		unsigned char *out,
144 		const unsigned char *in,
145         unsigned int inlen)
146 {
147 	unsigned char *A, B[16], *R;
148 	const unsigned char *iv = default_iv;
149 	unsigned int i, j, t;
150 	if ((inlen & 0x7) || (inlen < 8))
151 		return -1;
152 	A = B;
153 	t = 1;
154 	memcpy(out + 8, in, inlen);
155 
156 	memcpy(A, iv, 8);
157 
158 	for (j = 0; j < 6; j++)
159 	{
160 		R = out + 8;
161 		for (i = 0; i < inlen; i += 8, t++, R += 8)
162 		{
163 			memcpy(B + 8, R, 8);
164 			{
165 				size_t outlen = 16;
166 				cryspr_cb->cryspr->aes_ecb_cipher(true, &cryspr_cb->aes_kek, B, 16, B, &outlen);
167 			}
168 			A[7] ^= (unsigned char)(t & 0xff);
169 			if (t > 0xff)
170 			{
171 				A[6] ^= (unsigned char)((t >> 8) & 0xff);
172 				A[5] ^= (unsigned char)((t >> 16) & 0xff);
173 				A[4] ^= (unsigned char)((t >> 24) & 0xff);
174 			}
175 			memcpy(R, B + 8, 8);
176 		}
177 	}
178 	memcpy(out, A, 8);
179     return 0;
180 }
181 
crysprFallback_AES_UnwrapKey(CRYSPR_cb * cryspr_cb,unsigned char * out,const unsigned char * in,unsigned int inlen)182 int crysprFallback_AES_UnwrapKey(CRYSPR_cb *cryspr_cb,
183 		unsigned char *out,
184 		const unsigned char *in,
185         unsigned int inlen)
186 {
187 	unsigned char *A, B[16], *R;
188 	const unsigned char *iv = default_iv;
189 	unsigned int i, j, t;
190 	inlen -= 8;
191 	if (inlen & 0x7)
192 		return -1;
193 	if (inlen < 8)
194 		return -1;
195 	A = B;
196 	t =  6 * (inlen >> 3);
197 	memcpy(A, in, 8);
198 	memcpy(out, in + 8, inlen);
199 	for (j = 0; j < 6; j++)
200 	{
201 		R = out + inlen - 8;
202 		for (i = 0; i < inlen; i += 8, t--, R -= 8)
203 		{
204 			A[7] ^= (unsigned char)(t & 0xff);
205 			if (t > 0xff)
206 			{
207 				A[6] ^= (unsigned char)((t >> 8) & 0xff);
208 				A[5] ^= (unsigned char)((t >> 16) & 0xff);
209 				A[4] ^= (unsigned char)((t >> 24) & 0xff);
210 			}
211 			memcpy(B + 8, R, 8);
212 			{
213 				size_t outlen = 16;
214 				cryspr_cb->cryspr->aes_ecb_cipher(false, &cryspr_cb->aes_kek, B, 16, B, &outlen);
215 			}
216 			memcpy(R, B + 8, 8);
217 		}
218 	}
219 	if (memcmp(A, iv, 8))
220 	{
221 		memset(out, 0, inlen);
222         return -1;
223 	}
224     return 0;
225 }
226 
_crysprFallback_GetOutbuf(CRYSPR_cb * cryspr_cb,size_t pfx_len,size_t out_len)227 static unsigned char *_crysprFallback_GetOutbuf(CRYSPR_cb *cryspr_cb, size_t pfx_len, size_t out_len)
228 {
229 	unsigned char *out_buf;
230 
231 	if ((pfx_len + out_len) > (cryspr_cb->outbuf_siz - cryspr_cb->outbuf_ofs)) {
232 		/* Not enough room left, circle buffers */
233 		cryspr_cb->outbuf_ofs = 0;
234 	}
235 	out_buf = &cryspr_cb->outbuf[cryspr_cb->outbuf_ofs];
236 	cryspr_cb->outbuf_ofs += (pfx_len + out_len);
237 	return(out_buf);
238 }
239 
crysprFallback_Open(CRYSPR_methods * cryspr,size_t max_len)240 static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len)
241 {
242 	CRYSPR_cb *cryspr_cb;
243 	unsigned char *membuf;
244 	size_t memsiz, padded_len = hcryptMsg_PaddedLen(max_len, 128/8);
245 
246 	HCRYPT_LOG(LOG_DEBUG, "%s", "Using OpenSSL AES\n");
247 
248 	memsiz = sizeof(*cryspr_cb) + (CRYSPR_OUTMSGMAX * padded_len);
249 #if !CRYSPR_HAS_AESCTR
250 	memsiz += HCRYPT_CTR_STREAM_SZ;
251 #endif /* !CRYSPR_HAS_AESCTR */
252 
253 	cryspr_cb = malloc(memsiz);
254 	if (NULL == cryspr_cb) {
255 		HCRYPT_LOG(LOG_ERR, "malloc(%zd) failed\n", memsiz);
256 		return(NULL);
257 	}
258 	membuf = (unsigned char *)cryspr_cb;
259 	membuf += sizeof(*cryspr_cb);
260 
261 #if !CRYSPR_HAS_AESCTR
262 	cryspr_cb->ctr_stream = membuf;
263 	membuf += HCRYPT_CTR_STREAM_SZ;
264 	cryspr_cb->ctr_stream_siz = HCRYPT_CTR_STREAM_SZ;
265 	cryspr_cb->ctr_stream_len = 0;
266 #endif /* !CRYSPR_HAS_AESCTR */
267 
268 	cryspr_cb->outbuf = membuf;
269 	cryspr_cb->outbuf_siz = CRYSPR_OUTMSGMAX * padded_len;
270 	cryspr_cb->outbuf_ofs = 0;
271 //	membuf += cryspr_cb->outbuf_siz;
272 
273 	cryspr_cb->cryspr=(CRYSPR_methods *)cryspr;
274 
275 	return(cryspr_cb);
276 }
277 
crysprFallback_Close(CRYSPR_cb * cryspr_cb)278 static int crysprFallback_Close(CRYSPR_cb *cryspr_cb)
279 {
280 	free(cryspr_cb);
281 	return(0);
282 }
283 
crysprFallback_MsSetKey(CRYSPR_cb * cryspr_cb,hcrypt_Ctx * ctx,const unsigned char * key,size_t key_len)284 static int crysprFallback_MsSetKey(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx, const unsigned char *key, size_t key_len)
285 {
286 	CRYSPR_AESCTX *aes_sek = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)]; /* Ctx tells if it's for odd or even key */
287 
288 	if ((ctx->flags & HCRYPT_CTX_F_ENCRYPT)        /* Encrypt key */
289 	||  (ctx->mode == HCRYPT_CTX_MODE_AESCTR)) {   /* CTR mode decrypts using encryption methods */
290 		if (cryspr_cb->cryspr->aes_set_key(true, key, key_len, aes_sek)) {
291 			HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_encrypt_key(sek) failed\n");
292 			return(-1);
293 		}
294 	} else {                                       /* Decrypt key */
295 		if (cryspr_cb->cryspr->aes_set_key(false, key, key_len, aes_sek)) {
296 			HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_decrypt_key(sek) failed\n");
297 			return(-1);
298 		}
299 	}
300 	return(0);
301 }
302 
303 #if !CRYSPR_HAS_AESCTR
_crysprFallback_AES_SetCtrStream(CRYSPR_cb * cryspr_cb,hcrypt_Ctx * ctx,size_t len,unsigned char * iv)304 static int _crysprFallback_AES_SetCtrStream(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx, size_t len, unsigned char *iv)
305 {
306 	/* Counter stream:
307 	 *   0   1   2   3   4   5     nblk
308 	 * +---+---+---+---+---+---+---+---+
309 	 * |blk|blk|blk|blk|blk|blk|...|blk|
310 	 * +---+---+---+---+---+---+---+---+
311 	 */
312 
313 	/* IV (128-bit):
314 	 *    0   1   2   3   4   5  6   7   8   9   10  11  12  13  14  15
315 	 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
316 	 * |                   0s                  |      pki      |  ctr  |
317 	 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
318 	 *                            XOR
319 	 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
320 	 * |                         nonce                         +
321 	 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
322 	 *
323 	 * pki    (32-bit): packet index
324 	 * ctr    (16-bit): block counter
325 	 * nonce (112-bit): number used once (salt)
326 	 */
327 	unsigned char ctr[HCRYPT_CTR_BLK_SZ];
328 	unsigned nblk;
329 
330 	ASSERT(NULL != cryspr_cb);
331 	ASSERT(NULL != ctx);
332 
333 	memcpy(ctr, iv, HCRYPT_CTR_BLK_SZ);
334 
335 	nblk = (len + (HCRYPT_CTR_BLK_SZ-1))/HCRYPT_CTR_BLK_SZ;
336 	if ((nblk * HCRYPT_CTR_BLK_SZ) <= cryspr_cb->ctr_stream_siz) {
337 		unsigned blk;
338 		unsigned char *csp = &cryspr_cb->ctr_stream[0];
339 
340 		for(blk = 0; blk < nblk; blk++) {
341 			memcpy(csp, ctr, HCRYPT_CTR_BLK_SZ);
342 			csp += HCRYPT_CTR_BLK_SZ;
343 			if (0 == ++(ctr[HCRYPT_CTR_BLK_SZ-1])) ++(ctr[HCRYPT_CTR_BLK_SZ-2]);
344 		}
345 		cryspr_cb->ctr_stream_len = nblk * HCRYPT_CTR_BLK_SZ;
346 	} else {
347 		HCRYPT_LOG(LOG_ERR, "packet too long(%zd)\n", len);
348 		return(-1);
349 	}
350 	return(0);
351 }
352 #endif
353 
crysprFallback_MsEncrypt(CRYSPR_cb * cryspr_cb,hcrypt_Ctx * ctx,hcrypt_DataDesc * in_data,int nbin ATR_UNUSED,void * out_p[],size_t out_len_p[],int * nbout_p)354 static int crysprFallback_MsEncrypt(
355 	CRYSPR_cb *cryspr_cb,
356 	hcrypt_Ctx *ctx,
357 	hcrypt_DataDesc *in_data, int nbin ATR_UNUSED,
358 	void *out_p[], size_t out_len_p[], int *nbout_p)
359 {
360 	unsigned char *out_msg;
361 	size_t out_len = 0;	//payload size
362 	int pfx_len;
363 
364 	ASSERT(NULL != ctx);
365 	ASSERT(NULL != cryspr_cb);
366 	ASSERT((NULL != in_data) || (1 == nbin)); //Only one in_data[] supported
367 
368 	/*
369 	 * Get message prefix length
370 	 * to reserve room for unencrypted message header in output buffer
371 	 */
372 	pfx_len = ctx->msg_info->pfx_len;
373 
374 	/* Get buffer room from the internal circular output buffer */
375 	out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, in_data[0].len);
376 
377 	if (NULL != out_msg) {
378 		switch(ctx->mode) {
379 			case HCRYPT_CTX_MODE_AESCTR: /* Counter mode */
380 			{
381 #if CRYSPR_HAS_AESCTR
382 				/* Get current key (odd|even) from context */
383 				CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
384 				unsigned char iv[CRYSPR_AESBLKSZ];
385 
386 				/* Get input packet index (in network order) */
387 				hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
388 
389 				/*
390 				 * Compute the Initial Vector
391 				 * IV (128-bit):
392 				 *    0   1   2   3   4   5  6   7   8   9   10  11  12  13  14  15
393 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
394 				 * |                   0s                  |      pki      |  ctr  |
395 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
396 				 *                            XOR
397 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
398 				 * |                         nonce                         +
399 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
400 				 *
401 				 * pki    (32-bit): packet index
402 				 * ctr    (16-bit): block counter
403 				 * nonce (112-bit): number used once (salt)
404 				 */
405 				hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
406 
407 				cryspr_cb->cryspr->aes_ctr_cipher(true, aes_key, iv, in_data[0].payload, in_data[0].len,
408 						&out_msg[pfx_len]);
409 #else /*CRYSPR_HAS_AESCTR*/
410 				/* Get current key (odd|even) from context */
411 				CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
412 				unsigned char iv[CRYSPR_AESBLKSZ];
413 				int iret = 0;
414 
415 				/* Get input packet index (in network order) */
416 				hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
417 
418 				/*
419 				 * Compute the Initial Vector
420 				 * IV (128-bit):
421 				 *    0   1   2   3   4   5  6   7   8   9   10  11  12  13  14  15
422 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
423 				 * |                   0s                  |      pki      |  ctr  |
424 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
425 				 *                            XOR
426 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
427 				 * |                         nonce                         +
428 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
429 				 *
430 				 * pki    (32-bit): packet index
431 				 * ctr    (16-bit): block counter
432 				 * nonce (112-bit): number used once (salt)
433 				 */
434 				hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
435 
436 				/* Create CtrStream. May be longer than in_len (next cryspr block size boundary) */
437 				iret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv);
438 				if (iret) {
439 					return(iret);
440 				}
441 				/* Reserve output buffer for cryspr */
442 				out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, cryspr_cb->ctr_stream_len);
443 
444 				/* Create KeyStream (encrypt CtrStream) */
445 				iret = cryspr_cb->cryspr->aes_ecb_cipher(true, aes_key,
446 						cryspr_cb->ctr_stream, cryspr_cb->ctr_stream_len,
447 						&out_msg[pfx_len], &out_len);
448 				if (iret) {
449 					HCRYPT_LOG(LOG_ERR, "%s", "hcOpenSSL_AES_ecb_cipher(encrypt, failed\n");
450 					return(iret);
451 				}
452 #endif/*CRYSPR_HAS_AESCTR*/
453 				/* Prepend packet prefix (clear text) in output buffer */
454 				memcpy(out_msg, in_data[0].pfx, pfx_len);
455 				/* CTR mode output length is same as input, no padding */
456 				out_len = in_data[0].len;
457 				break;
458 			}
459 			case HCRYPT_CTX_MODE_CLRTXT:    /* Clear text mode (transparent mode for tests) */
460 				memcpy(&out_msg[pfx_len], in_data[0].payload, in_data[0].len);
461 				memcpy(out_msg, in_data[0].pfx, pfx_len);
462 				out_len = in_data[0].len;
463 				break;
464 			default:
465 				/* Unsupported cipher mode */
466 				return(-1);
467 		}
468 	} else {
469 		/* input data too big */
470 		return(-1);
471 	}
472 
473 	if (out_len > 0) {
474 		/* Encrypted messages have been produced */
475 		if (NULL == out_p) {
476 			/*
477 			 * Application did not provided output buffer,
478 			 * so copy encrypted message back in input buffer
479 			 */
480 			memcpy(in_data[0].pfx, out_msg, pfx_len);
481 #if !CRYSPR_HAS_AESCTR
482 			if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
483 				/* XOR KeyStream with input text directly in input buffer */
484 				hcrypt_XorStream(in_data[0].payload, &out_msg[pfx_len], out_len);
485 			}else{
486 				/* Copy output data back in input buffer */
487 				memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
488 			}
489 #else /* CRYSPR_HAS_AESCTR */
490 			/* Copy output data back in input buffer */
491 			memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
492 #endif /* CRYSPR_HAS_AESCTR */
493 		} else {
494 			/* Copy header in output buffer if needed */
495 			if (pfx_len > 0) memcpy(out_msg, in_data[0].pfx, pfx_len);
496 #if !CRYSPR_HAS_AESCTR
497 			if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
498 				hcrypt_XorStream(&out_msg[pfx_len], in_data[0].payload, out_len);
499 			}
500 #endif /* CRYSPR_HAS_AESCTR */
501 			out_p[0] = out_msg;
502 			out_len_p[0] = pfx_len + out_len;
503 			*nbout_p = 1;
504 		}
505 	} else {
506 		/*
507 		 * Nothing out
508 		 * This is not an error for implementations using deferred/async processing
509 		 * with co-processor, DSP, crypto hardware, etc.
510 		 * Submitted input data could be returned encrypted in a next call.
511 		 */
512 		if (nbout_p != NULL) *nbout_p = 0;
513 		return(-1);
514 	}
515 	return(0);
516 }
517 
crysprFallback_MsDecrypt(CRYSPR_cb * cryspr_cb,hcrypt_Ctx * ctx,hcrypt_DataDesc * in_data,int nbin ATR_UNUSED,void * out_p[],size_t out_len_p[],int * nbout_p)518 static int crysprFallback_MsDecrypt(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx,
519 	hcrypt_DataDesc *in_data, int nbin ATR_UNUSED, void *out_p[], size_t out_len_p[], int *nbout_p)
520 {
521 	unsigned char *out_txt;
522 	size_t out_len;
523 	int iret = 0;
524 
525 	ASSERT(NULL != cryspr_cb);
526 	ASSERT(NULL != ctx);
527 	ASSERT((NULL != in_data) || (1 == nbin)); //Only one in_data[] supported
528 
529 	/* Reserve output buffer (w/no header) */
530 	out_txt = _crysprFallback_GetOutbuf(cryspr_cb, 0, in_data[0].len);
531 
532 	if (NULL != out_txt) {
533 		switch(ctx->mode) {
534 			case HCRYPT_CTX_MODE_AESCTR:
535 			{
536 #if CRYSPR_HAS_AESCTR
537 				/* Get current key (odd|even) from context */
538 				CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
539 				unsigned char iv[CRYSPR_AESBLKSZ];
540 
541 				/* Get input packet index (in network order) */
542 				hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
543 
544 				/*
545 				 * Compute the Initial Vector
546 				 * IV (128-bit):
547 				 *    0   1   2   3   4   5  6   7   8   9   10  11  12  13  14  15
548 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
549 				 * |                   0s                  |      pki      |  ctr  |
550 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
551 				 *                            XOR
552 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
553 				 * |                         nonce                         +
554 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
555 				 *
556 				 * pki    (32-bit): packet index
557 				 * ctr    (16-bit): block counter
558 				 * nonce (112-bit): number used once (salt)
559 				 */
560 				hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
561 
562 				cryspr_cb->cryspr->aes_ctr_cipher(false, aes_key, iv, in_data[0].payload, in_data[0].len,
563 						out_txt);
564 				out_len = in_data[0].len;
565 #else  /*CRYSPR_HAS_AESCTR*/
566 				/* Get current key (odd|even) from context */
567 				CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
568 				unsigned char iv[CRYSPR_AESBLKSZ];
569 				int iret = 0;
570 
571 				/* Get input packet index (in network order) */
572 				hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
573 
574 				/*
575 				 * Compute the Initial Vector
576 				 * IV (128-bit):
577 				 *    0   1   2   3   4   5  6   7   8   9   10  11  12  13  14  15
578 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
579 				 * |                   0s                  |      pki      |  ctr  |
580 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
581 				 *                            XOR
582 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
583 				 * |                         nonce                         +
584 				 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
585 				 *
586 				 * pki    (32-bit): packet index
587 				 * ctr    (16-bit): block counter
588 				 * nonce (112-bit): number used once (salt)
589 				 */
590 				hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
591 
592 				/* Create CtrStream. May be longer than in_len (next cipher block size boundary) */
593 				iret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv);
594 				if (iret) {
595 					return(iret);
596 				}
597 				/* Reserve output buffer for cryspr */
598 				out_txt = _crysprFallback_GetOutbuf(cryspr_cb, 0, cryspr_cb->ctr_stream_len);
599 
600 				/* Create KeyStream (encrypt CtrStream) */
601 				iret = cryspr_cb->cryspr->aes_ecb_cipher(true, aes_key,
602 						cryspr_cb->ctr_stream, cryspr_cb->ctr_stream_len,
603 						out_txt, &out_len);
604 				if (iret) {
605 					HCRYPT_LOG(LOG_ERR, "%s", "crysprNatural_AES_ecb_cipher(encrypt failed\n");
606 					return(iret);
607 				}
608 
609 #endif /*CRYSPR_HAS_AESCTR*/
610 				break;
611 			}
612 			case HCRYPT_CTX_MODE_CLRTXT:
613 				memcpy(out_txt, in_data[0].payload, in_data[0].len);
614 				out_len = in_data[0].len;
615 				break;
616 			default:
617 				return(-1);
618 		}
619 	} else {
620 		return(-1);
621 	}
622 
623 	if (out_len > 0) {
624 		if (NULL == out_p) {
625 			/*
626 			 * Application did not provided output buffer,
627 			 * so copy encrypted message back in input buffer
628 			 */
629 #if !CRYSPR_HAS_AESCTR
630 			if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
631 				/* XOR KeyStream with input text directly in input buffer */
632 				hcrypt_XorStream(in_data[0].payload, out_txt, out_len);
633 			}else{
634 				/* Copy output data back in input buffer */
635 				memcpy(in_data[0].payload, out_txt, out_len);
636 			}
637 #else /* CRYSPR_HAS_AESCTR */
638 			/* Copy output data back in input buffer */
639 			memcpy(in_data[0].payload, out_txt, out_len);
640 #endif /* CRYSPR_HAS_AESCTR */
641 		} else {
642 			/* Copy header in output buffer if needed */
643 #if !CRYSPR_HAS_AESCTR
644 			if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
645 				hcrypt_XorStream(out_txt, in_data[0].payload, out_len);
646 			}
647 #endif /* CRYSPR_HAS_AESCTR */
648 			out_p[0] = out_txt;
649 			out_len_p[0] = out_len;
650 			*nbout_p = 1;
651 		}
652 		iret = 0;
653 	} else {
654 		if (NULL != nbout_p) *nbout_p = 0;
655 		iret = -1;
656 	}
657 
658 #if 0
659 	{	/* Debug decryption errors */
660 		static int nberr = 0;
661 
662 		if (out_txt[0] != 0x47){
663 			if ((++nberr == 1)
664 					||  ((nberr > 500) && (0 == ((((unsigned char *)&MSmsg->pki)[2] & 0x0F)|((unsigned char *)&MSmsg->pki)[3])))) {
665 				HCRYPT_LOG(LOG_DEBUG, "keyindex=%d\n", hcryptCtx_GetKeyIndex(ctx));
666 				HCRYPT_PRINTKEY(ctx->sek, ctx->sek_len, "sek");
667 				HCRYPT_PRINTKEY(ctx->salt, ctx->salt_len, "salt");
668 			}
669 		} else {
670 			nberr = 0;
671 		}
672 	}
673 #endif
674 	return(iret);
675 }
676 
677 
crysprInit(CRYSPR_methods * cryspr)678 CRYSPR_methods *crysprInit(CRYSPR_methods *cryspr)
679 {
680 	/* CryptoLib Primitive API */
681 	cryspr->prng            = crysprStub_Prng;
682 	cryspr->aes_set_key     = crysprStub_AES_SetKey;
683 	cryspr->aes_ecb_cipher  = crysprStub_AES_EcbCipher;
684 	cryspr->aes_ctr_cipher  = crysprStub_AES_CtrCipher;
685 	cryspr->sha1_msg_digest = crysprStub_SHA1_MsgDigest;
686 
687 
688 	/* Crypto Session API */
689 	cryspr->open       = crysprFallback_Open;
690 	cryspr->close      = crysprFallback_Close;
691 	//Keying material (km) encryption
692 	cryspr->km_pbkdf2  = crysprStub_KmPbkdf2;
693 	cryspr->km_setkey  = crysprFallback_KmSetKey;
694 	cryspr->km_wrap    = crysprFallback_AES_WrapKey;
695 	cryspr->km_unwrap  = crysprFallback_AES_UnwrapKey;
696 	//Media stream (ms) encryption
697 	cryspr->ms_setkey  = crysprFallback_MsSetKey;
698 	cryspr->ms_encrypt = crysprFallback_MsEncrypt;
699 	cryspr->ms_decrypt = crysprFallback_MsDecrypt;
700 
701 	return(cryspr);
702 }
703 
HaiCryptCryspr_Get_Instance(void)704 HaiCrypt_Cryspr HaiCryptCryspr_Get_Instance(void)
705 {
706     return((HaiCrypt_Cryspr)cryspr4SRT());
707 }
708