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 <sys/types.h>
23 #include <stdlib.h>     /* NULL */
24 #include <string.h>     /* memcpy */
25 #ifdef _WIN32
26     #include <winsock2.h>
27     #include <ws2tcpip.h>
28     #include <stdint.h>
29 #else
30     #include <arpa/inet.h>  /* htonl */
31 #endif
32 #include "hcrypt.h"
33 
HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc,size_t data_len,unsigned char ** in_pp)34 int HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc, size_t data_len, unsigned char **in_pp)
35 {
36 	hcrypt_Session *crypto = (hcrypt_Session *)hhc;
37 
38 	ASSERT(NULL != crypto);
39 	ASSERT(NULL != crypto->cryspr);
40 
41 	int pad_factor = (HCRYPT_CTX_MODE_AESECB == crypto->ctx->mode ? 128/8 : 1);
42 
43 #ifndef _WIN32
44 	ASSERT(crypto->inbuf != NULL);
45 #endif
46 	size_t in_len = crypto->msg_info->pfx_len + hcryptMsg_PaddedLen(data_len, pad_factor);
47 	*in_pp = crypto->inbuf;
48 	if (in_len > crypto->inbuf_siz) {
49 		*in_pp = NULL;
50 		return(-1);
51 	}
52 	return(crypto->msg_info->pfx_len);
53 }
54 
HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc,void * out_p[],size_t out_len_p[],int maxout)55 int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout)
56 {
57 	hcrypt_Session *crypto = (hcrypt_Session *)hhc;
58 	hcrypt_Ctx *ctx = crypto->ctx;
59 	int nbout = 0;
60 
61 	if ((NULL == crypto)
62 	||  (NULL == ctx)
63 	||  (NULL == out_p)
64 	||  (NULL == out_len_p)) {
65 		HCRYPT_LOG(LOG_ERR, "ManageKeys: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
66 		return(-1);
67 	}
68 
69 	/* Manage Key Material (refresh, announce, decommission) */
70 	hcryptCtx_Tx_ManageKM(crypto);
71 
72 	ctx = crypto->ctx;
73 	if (NULL == ctx) {
74 		HCRYPT_LOG(LOG_ERR, "%s", "crypto context not defined\n");
75 		return(-1);
76 	}
77 	ASSERT(ctx->status == HCRYPT_CTX_S_ACTIVE);
78 
79 	nbout = hcryptCtx_Tx_InjectKM(crypto, out_p, out_len_p, maxout);
80 	return(nbout);
81 }
82 
HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc)83 int HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc)
84 {
85 	hcrypt_Session *crypto = (hcrypt_Session *)hhc;
86 	hcrypt_Ctx *ctx = crypto->ctx;
87 
88 	if ((NULL == crypto)
89 	||  (NULL == ctx)){
90 		HCRYPT_LOG(LOG_ERR, "GetKeyFlags: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
91 		return(-1);
92 	}
93 	return(hcryptCtx_GetKeyFlags(ctx));
94 }
95 
HaiCrypt_Tx_Data(HaiCrypt_Handle hhc,unsigned char * in_pfx,unsigned char * in_data,size_t in_len)96 int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc,
97 	unsigned char *in_pfx, unsigned char *in_data, size_t in_len)
98 {
99 	hcrypt_Session *crypto = (hcrypt_Session *)hhc;
100 	hcrypt_Ctx *ctx = crypto->ctx;
101 	int nbout = 0;
102 
103 	if ((NULL == crypto)
104 	||  (NULL == ctx)){
105 		HCRYPT_LOG(LOG_ERR, "Tx_Data: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
106 		return(-1);
107 	}
108 	/* Get/Set packet index */
109 	ctx->msg_info->indexMsg(in_pfx, ctx->MSpfx_cache);
110 
111 	/* Encrypt */
112 	{
113 		hcrypt_DataDesc indata;
114 		indata.pfx      = in_pfx;
115 		indata.payload  = in_data;
116 		indata.len      = in_len;
117 
118 		if (0 > (nbout = crypto->cryspr->ms_encrypt(crypto->cryspr_cb, ctx, &indata, 1, NULL, NULL, NULL))) {
119 			HCRYPT_LOG(LOG_ERR, "%s", "ms_encrypt failed\n");
120 			return(nbout);
121 		}
122 	}
123 	ctx->pkt_cnt++;
124 
125 	return(nbout);
126 }
127 
HaiCrypt_Tx_Process(HaiCrypt_Handle hhc,unsigned char * in_msg,size_t in_len,void * out_p[],size_t out_len_p[],int maxout)128 int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc,
129 	unsigned char *in_msg, size_t in_len,
130 	void *out_p[], size_t out_len_p[], int maxout)
131 {
132 	hcrypt_Session *crypto = (hcrypt_Session *)hhc;
133 	hcrypt_Ctx *ctx = crypto->ctx;
134 	int nb, nbout = 0;
135 
136 	if ((NULL == crypto)
137 	||  (NULL == ctx)
138 	||  (NULL == out_p)
139 	||  (NULL == out_len_p)) {
140 		HCRYPT_LOG(LOG_ERR, "Tx_Process: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
141 		return(-1);
142 	}
143 
144 	/* Manage Key Material (refresh, announce, decommission) */
145 	hcryptCtx_Tx_ManageKM(crypto);
146 
147 	ctx = crypto->ctx;
148 	if (NULL == ctx) {
149 		HCRYPT_LOG(LOG_ERR, "%s", "crypto context not defined\n");
150 		return(-1);
151 	}
152 	ASSERT(ctx->status == HCRYPT_CTX_S_ACTIVE);
153 
154 	nbout += hcryptCtx_Tx_InjectKM(crypto, out_p, out_len_p, maxout);
155 
156 	/* Get packet index */
157 	ctx->msg_info->indexMsg(in_msg, ctx->MSpfx_cache);
158 
159 	/* Encrypt */
160 	nb = maxout - nbout;
161 	{
162 		hcrypt_DataDesc indata;
163 		indata.pfx      = in_msg;
164 		indata.payload  = &in_msg[ctx->msg_info->pfx_len];
165 		indata.len      = in_len - ctx->msg_info->pfx_len;
166 
167 		if (crypto->cryspr->ms_encrypt(crypto->cryspr_cb, ctx, &indata, 1, &out_p[nbout], &out_len_p[nbout], &nb)) {
168 			HCRYPT_LOG(LOG_ERR, "%s", "ms_encrypt failed\n");
169 			return(nbout);
170 		}
171 	}
172 	nbout += nb;
173 	ctx->pkt_cnt++;
174 
175 	return(nbout);
176 }
177