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 2014-03-11 (jdube)
17 Adaptation for SRT.
18 *****************************************************************************/
19
20 #include <string.h> /* memset, memcpy */
21 #ifdef _WIN32
22 #include <winsock2.h>
23 #include <ws2tcpip.h>
24 #else
25 #include <arpa/inet.h> /* htonl, ntohl */
26 #endif
27 #include "hcrypt.h"
28
29 /*
30 * HaiCrypt SRT (Secure Reliable Transport) Media Stream (MS) Msg Prefix:
31 * This is UDT data header with Crypto Key Flags (KF) added.
32 * Header is in 32bit host order words in the context of the functions of this handler.
33 *
34 * 0 1 2 3
35 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
36 * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
37 * 0x00 |0| Packet Sequence Number (pki) |
38 * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
39 * 0x04 |FF |o|KF | Message Number |
40 * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
41 * 0x08 | Time Stamp |
42 * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
43 * 0x0C | Destination Socket ID) |
44 * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
45 * | Payload... |
46 */
47
48
49 /*
50 * HaiCrypt Standalone Transport Keying Material (KM) Msg header kept in SRT
51 * Message and cache maintained in network order
52 *
53 * 0 1 2 3
54 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
55 * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
56 * 0x00 |0|Vers | PT | Sign | resv |
57 * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
58 * ... .
59 */
60
61 #define HCRYPT_MSG_SRT_HDR_SZ 16
62 #define HCRYPT_MSG_SRT_PFX_SZ 16
63
64 #define HCRYPT_MSG_SRT_OFS_PKI 0
65 #define HCRYPT_MSG_SRT_OFS_MSGNO 4
66 #define HCRYPT_MSG_SRT_SHF_KFLGS 27 //shift
67
68 static hcrypt_MsgInfo _hcMsg_SRT_MsgInfo;
69
hcryptMsg_SRT_GetKeyFlags(unsigned char * msg)70 static unsigned hcryptMsg_SRT_GetKeyFlags(unsigned char *msg)
71 {
72 uint32_t msgno;
73 memcpy(&msgno, &msg[HCRYPT_MSG_SRT_OFS_MSGNO], sizeof(msgno)); //header is in host order
74 return((unsigned)((msgno >> HCRYPT_MSG_SRT_SHF_KFLGS) & HCRYPT_MSG_F_xSEK));
75 }
76
hcryptMsg_SRT_GetPki(unsigned char * msg,int nwkorder)77 static hcrypt_Pki hcryptMsg_SRT_GetPki(unsigned char *msg, int nwkorder)
78 {
79 hcrypt_Pki pki;
80 memcpy(&pki, &msg[HCRYPT_MSG_SRT_OFS_PKI], sizeof(pki)); //header is in host order
81 return (nwkorder ? htonl(pki) : pki);
82 }
83
hcryptMsg_SRT_SetPki(unsigned char * msg,hcrypt_Pki pki)84 static void hcryptMsg_SRT_SetPki(unsigned char *msg, hcrypt_Pki pki)
85 {
86 memcpy(&msg[HCRYPT_MSG_SRT_OFS_PKI], &pki, sizeof(pki)); //header is in host order
87 }
88
hcryptMsg_SRT_ResetCache(unsigned char * pfx_cache,unsigned pkt_type,unsigned kflgs)89 static void hcryptMsg_SRT_ResetCache(unsigned char *pfx_cache, unsigned pkt_type, unsigned kflgs)
90 {
91 switch(pkt_type) {
92 case HCRYPT_MSG_PT_MS: /* Media Stream */
93 /* Nothing to do, header filled by protocol */
94 break;
95 case HCRYPT_MSG_PT_KM: /* Keying Material */
96 pfx_cache[HCRYPT_MSG_KM_OFS_VERSION] = (unsigned char)((HCRYPT_MSG_VERSION << 4) | pkt_type); // version || PT
97 pfx_cache[HCRYPT_MSG_KM_OFS_SIGN] = (unsigned char)((HCRYPT_MSG_SIGN >> 8) & 0xFF); // Haivision PnP Mfr ID
98 pfx_cache[HCRYPT_MSG_KM_OFS_SIGN+1] = (unsigned char)(HCRYPT_MSG_SIGN & 0xFF);
99 pfx_cache[HCRYPT_MSG_KM_OFS_KFLGS] = (unsigned char)kflgs; //HCRYPT_MSG_F_xxx
100 break;
101 default:
102 break;
103 }
104 }
105
hcryptMsg_SRT_IndexMsg(unsigned char * msg,unsigned char * pfx_cache)106 static void hcryptMsg_SRT_IndexMsg(unsigned char *msg, unsigned char *pfx_cache)
107 {
108 (void)msg;
109 (void)pfx_cache;
110 return; //nothing to do, header and index maintained by SRT
111 }
112
hcryptMsg_SRT_ParseMsg(unsigned char * msg)113 static int hcryptMsg_SRT_ParseMsg(unsigned char *msg)
114 {
115 int rc;
116
117 if ((HCRYPT_MSG_VERSION == hcryptMsg_KM_GetVersion(msg)) /* Version 1 */
118 && (HCRYPT_MSG_PT_KM == hcryptMsg_KM_GetPktType(msg)) /* Keying Material */
119 && (HCRYPT_MSG_SIGN == hcryptMsg_KM_GetSign(msg))) { /* 'HAI' PnP Mfr ID */
120 rc = HCRYPT_MSG_PT_KM;
121 } else {
122 //Assume it's data.
123 //SRT does not call this for MS msg
124 rc = HCRYPT_MSG_PT_MS;
125 }
126
127 switch(rc) {
128 case HCRYPT_MSG_PT_MS:
129 if (hcryptMsg_HasNoSek(&_hcMsg_SRT_MsgInfo, msg)
130 || hcryptMsg_HasBothSek(&_hcMsg_SRT_MsgInfo, msg)) {
131 HCRYPT_LOG(LOG_ERR, "invalid MS msg flgs: %02x\n",
132 hcryptMsg_GetKeyIndex(&_hcMsg_SRT_MsgInfo, msg));
133 return(-1);
134 }
135 break;
136 case HCRYPT_MSG_PT_KM:
137 if (HCRYPT_SE_TSSRT != hcryptMsg_KM_GetSE(msg)) { //Check Stream Encapsulation (SE)
138 HCRYPT_LOG(LOG_ERR, "invalid KM msg SE: %d\n",
139 hcryptMsg_KM_GetSE(msg));
140 return(-1);
141 }
142 if (hcryptMsg_KM_HasNoSek(msg)) {
143 HCRYPT_LOG(LOG_ERR, "invalid KM msg flgs: %02x\n",
144 hcryptMsg_KM_GetKeyIndex(msg));
145 return(-1);
146 }
147 break;
148 default:
149 HCRYPT_LOG(LOG_ERR, "invalid pkt type: %d\n", rc);
150 rc = 0; /* unknown packet type */
151 break;
152 }
153 return(rc); /* -1: error, 0: unknown: >0: PT */
154 }
155
156 static hcrypt_MsgInfo _hcMsg_SRT_MsgInfo;
157
hcryptMsg_SRT_MsgInfo(void)158 hcrypt_MsgInfo *hcryptMsg_SRT_MsgInfo(void)
159 {
160 _hcMsg_SRT_MsgInfo.hdr_len = HCRYPT_MSG_SRT_HDR_SZ;
161 _hcMsg_SRT_MsgInfo.pfx_len = HCRYPT_MSG_SRT_PFX_SZ;
162 _hcMsg_SRT_MsgInfo.getKeyFlags = hcryptMsg_SRT_GetKeyFlags;
163 _hcMsg_SRT_MsgInfo.getPki = hcryptMsg_SRT_GetPki;
164 _hcMsg_SRT_MsgInfo.setPki = hcryptMsg_SRT_SetPki;
165 _hcMsg_SRT_MsgInfo.resetCache = hcryptMsg_SRT_ResetCache;
166 _hcMsg_SRT_MsgInfo.indexMsg = hcryptMsg_SRT_IndexMsg;
167 _hcMsg_SRT_MsgInfo.parseMsg = hcryptMsg_SRT_ParseMsg;
168
169 return(&_hcMsg_SRT_MsgInfo);
170 }
171
172