1 /*
2  * SRT - Secure, Reliable, Transport
3  * Copyright (c) 2018 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    2011-06-23 (jdube)
17         HaiCrypt initial implementation.
18    2014-03-11 (jdube)
19         Adaptation for SRT.
20 *****************************************************************************/
21 
22 #include <stdlib.h>				/* NULL */
23 #include <string.h>				/* memcmp */
24 #include "hcrypt.h"
25 
HaiCrypt_Rx_Data(HaiCrypt_Handle hhc,unsigned char * in_pfx,unsigned char * data,size_t data_len)26 int HaiCrypt_Rx_Data(HaiCrypt_Handle hhc,
27 	unsigned char *in_pfx, unsigned char *data, size_t data_len)
28 {
29 	hcrypt_Session *crypto = (hcrypt_Session *)hhc;
30 	hcrypt_Ctx *ctx;
31 	int nb = -1;
32 
33 	if ((NULL == crypto)
34 	||  (NULL == data)) {
35 		HCRYPT_LOG(LOG_ERR, "%s", "invalid parameters\n");
36 		return(nb);
37 	}
38 
39 	ctx = &crypto->ctx_pair[hcryptMsg_GetKeyIndex(crypto->msg_info, in_pfx)];
40 
41 	ASSERT(NULL != ctx); /* Header check should prevent this error */
42 	ASSERT(NULL != crypto->cryspr); /* Header check should prevent this error */
43 
44 	crypto->ctx = ctx; /* Context of last received msg */
45 	if (NULL == crypto->cryspr->ms_decrypt) {
46 		HCRYPT_LOG(LOG_ERR, "%s", "cryspr had no decryptor\n");
47 	} else if (ctx->status >= HCRYPT_CTX_S_KEYED) {
48 		hcrypt_DataDesc indata;
49 		indata.pfx      = in_pfx;
50 		indata.payload  = data;
51 		indata.len      = data_len;
52 
53 		if (0 > (nb = crypto->cryspr->ms_decrypt(crypto->cryspr_cb, ctx, &indata, 1, NULL, NULL, NULL))) {
54 			HCRYPT_LOG(LOG_ERR, "%s", "ms_decrypt failed\n");
55 		} else {
56 			nb = indata.len;
57 		}
58 	} else { /* No key received yet */
59 		nb = 0;
60 	}
61 	return(nb);
62 }
63 
HaiCrypt_Rx_Process(HaiCrypt_Handle hhc,unsigned char * in_msg,size_t in_len,void * out_p[],size_t out_len_p[],int maxout)64 int HaiCrypt_Rx_Process(HaiCrypt_Handle hhc,
65 	unsigned char *in_msg, size_t in_len,
66 	void *out_p[], size_t out_len_p[], int maxout)
67 {
68 	hcrypt_Session *crypto = (hcrypt_Session *)hhc;
69 	hcrypt_Ctx *ctx;
70 	int nbout = maxout;
71 	int msg_type;
72 
73 	if ((NULL == crypto)
74 	||  (NULL == in_msg)) {
75 
76 		HCRYPT_LOG(LOG_ERR, "%s", "invalid parameters\n");
77 		return(-1);
78 	}
79 
80 	/* Validate HaiCrypt message */
81 	if (0 > (msg_type = crypto->msg_info->parseMsg(in_msg))) {
82 		return(-1);
83 	}
84 
85 	switch(msg_type) {
86 	case HCRYPT_MSG_PT_MS: /* MSmsg */
87 		ctx = &crypto->ctx_pair[hcryptMsg_GetKeyIndex(crypto->msg_info, in_msg)];
88 
89 		if ((NULL == out_p)
90 		||  (NULL == out_len_p)) {
91 			HCRYPT_LOG(LOG_ERR, "%s", "invalid parameters\n");
92 			return(-1);
93 		}
94 		ASSERT(NULL != ctx); /* Header check should prevent this error */
95 		ASSERT(NULL != crypto->cryspr); /* Header check should prevent this error */
96 
97 		crypto->ctx = ctx; /* Context of last received msg */
98 		if (NULL == crypto->cryspr->ms_decrypt) {
99 			HCRYPT_LOG(LOG_ERR, "%s", "cryspr had no decryptor\n");
100 			nbout = -1;
101 		} else if (ctx->status >= HCRYPT_CTX_S_KEYED) {
102 			hcrypt_DataDesc indata;
103 			indata.pfx      = in_msg;
104 			indata.payload  = &in_msg[crypto->msg_info->pfx_len];
105 			indata.len      = in_len - crypto->msg_info->pfx_len;
106 
107 			if (crypto->cryspr->ms_decrypt(crypto->cryspr_cb, ctx, &indata, 1, out_p, out_len_p, &nbout)) {
108 				HCRYPT_LOG(LOG_ERR, "%s", "ms_decrypt failed\n");
109 				nbout = -1;
110 			}
111 		} else { /* No key received yet */
112 			nbout = 0;
113 		}
114 		break;
115 
116 	case HCRYPT_MSG_PT_KM: /* KMmsg */
117 		/* Even or Both SEKs check with even context */
118 		ctx = &crypto->ctx_pair[hcryptMsg_GetKeyIndex(crypto->msg_info, in_msg)];
119 
120 		ASSERT(NULL != ctx); /* Header check should prevent this error */
121 
122 		if ((ctx->status < HCRYPT_CTX_S_KEYED)	/* No key deciphered yet */
123 		||  (in_len != ctx->KMmsg_len) 				/* or not same size */
124 		||  (0 != memcmp(ctx->KMmsg_cache, in_msg, in_len))) { /* or different */
125 
126 			nbout = hcryptCtx_Rx_ParseKM(crypto, in_msg, in_len);
127 			//-2: unmatched shared secret
128 			//-1: other failures
129 			//0: success
130 		} else {
131 			nbout = 0;
132 		}
133 		if (NULL != out_p) out_p[0] = NULL;
134 		if (NULL != out_len_p) out_len_p[0] = 0;
135 		break;
136 
137 	default:
138 		HCRYPT_LOG(LOG_WARNING, "%s", "unknown packet type\n");
139 		nbout = 0;
140 		break;
141 	}
142 
143 	return(nbout);
144 }
145 
146 
147