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-26 (jdube)
17         OpenSSL CRYSPR/4SRT (CRYypto Service PRovider for SRT).
18 *****************************************************************************/
19 
20 #include "hcrypt.h"
21 
22 #include <string.h>
23 
24 
25 typedef struct tag_crysprOpenSSL_AES_cb {
26         CRYSPR_cb       ccb;
27         /* Add cryptolib specific data here */
28 } crysprOpenSSL_cb;
29 
30 
crysprOpenSSL_Prng(unsigned char * rn,int len)31 int crysprOpenSSL_Prng(unsigned char *rn, int len)
32 {
33     return(RAND_bytes(rn, len) <= 0 ? -1 : 0);
34 }
35 
crysprOpenSSL_AES_SetKey(bool bEncrypt,const unsigned char * kstr,size_t kstr_len,CRYSPR_AESCTX * aes_key)36 int crysprOpenSSL_AES_SetKey(
37     bool bEncrypt,              /* true Enxcrypt key, false: decrypt */
38     const unsigned char *kstr,  /* key sttring*/
39     size_t kstr_len,            /* kstr len in  bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
40     CRYSPR_AESCTX *aes_key)     /* CRYpto Service PRovider AES Key context */
41 {
42     if (bEncrypt) {        /* Encrypt key */
43         if (AES_set_encrypt_key(kstr, kstr_len * 8, aes_key)) {
44             HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) failed\n");
45             return(-1);
46         }
47     } else {               /* Decrypt key */
48         if (AES_set_decrypt_key(kstr, kstr_len * 8, aes_key)) {
49             HCRYPT_LOG(LOG_ERR, "%s", "AES_set_decrypt_key(kek) failed\n");
50             return(-1);
51         }
52     }
53     return(0);
54 }
55 
56 #if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP)
57 
crysprOpenSSL_AES_EcbCipher(bool bEncrypt,CRYSPR_AESCTX * aes_key,const unsigned char * indata,size_t inlen,unsigned char * out_txt,size_t * outlen)58 int crysprOpenSSL_AES_EcbCipher(
59     bool bEncrypt,              /* true:encrypt, false:decrypt */
60     CRYSPR_AESCTX *aes_key,     /* CRYpto Service PRovider AES Key context */
61     const unsigned char *indata,/* src (clear text if encrypt, cipher text otherwise)*/
62     size_t inlen,               /* indata length */
63     unsigned char *out_txt,     /* dst (cipher text if encrypt, clear text otherwise) */
64     size_t *outlen)             /* in/out dst len */
65 {
66     int nblk = inlen/CRYSPR_AESBLKSZ;
67     int nmore = inlen%CRYSPR_AESBLKSZ;
68     size_t outsiz = (outlen ? *outlen : 0);
69     int i;
70 
71     if (outsiz % CRYSPR_AESBLKSZ) return(-1); /* output buf size must be a multiple of AES block size (16) */
72     if (bEncrypt) {
73         if (outsiz > 16 && outsiz < (nblk+nmore)*CRYSPR_AESBLKSZ) return(-1); /* output buf size must have room for PKCS7 padding */
74         /* Encrypt packet payload, block by block, in output buffer */
75         for (i=0; i<nblk; i++){
76             AES_ecb_encrypt(&indata[(i*CRYSPR_AESBLKSZ)],
77                 &out_txt[(i*CRYSPR_AESBLKSZ)], aes_key, AES_ENCRYPT);
78         }
79         /* Encrypt last incomplete block */
80         if (0 < nmore) {
81             unsigned char intxt[CRYSPR_AESBLKSZ];
82             /* PKCS7 padding: padding value is number of bytes padded */
83             memcpy(intxt, &indata[(nblk*CRYSPR_AESBLKSZ)], nmore);
84             memset(intxt+nmore, CRYSPR_AESBLKSZ-nmore, CRYSPR_AESBLKSZ-nmore);
85             AES_ecb_encrypt(intxt, &out_txt[(nblk*CRYSPR_AESBLKSZ)], aes_key, AES_ENCRYPT);
86             nblk++;
87         }
88         if (outlen != NULL) *outlen = nblk*CRYSPR_AESBLKSZ;
89     } else { /* Decrypt */
90         for (i=0; i<nblk; i++){
91             AES_ecb_encrypt(&indata[(i*CRYSPR_AESBLKSZ)],
92                 &out_txt[(i*CRYSPR_AESBLKSZ)], aes_key, AES_DECRYPT);
93         }
94         /* Encrypt last incomplete block */
95         if (0 < nmore) {
96             //shall not happens in decrypt
97         }
98         if (outlen != NULL) *outlen = nblk*CRYSPR_AESBLKSZ;
99     }
100     return 0;
101 }
102 #endif /* !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP) */
103 
crysprOpenSSL_AES_CtrCipher(bool bEncrypt,CRYSPR_AESCTX * aes_key,unsigned char * iv,const unsigned char * indata,size_t inlen,unsigned char * out_txt)104 int crysprOpenSSL_AES_CtrCipher(
105     bool bEncrypt,              /* true:encrypt, false:decrypt */
106     CRYSPR_AESCTX *aes_key,     /* CRYpto Service PRovider AES Key context */
107     unsigned char *iv,          /* iv */
108     const unsigned char *indata,/* src */
109     size_t inlen,               /* length */
110     unsigned char *out_txt)     /* dest */
111 {
112     unsigned char ctr[CRYSPR_AESBLKSZ];
113     unsigned blk_ofs = 0;
114     (void)bEncrypt;             /* CTR mode encrypt for both encryption and decryption */
115 
116     memset(&ctr[0], 0, sizeof(ctr));
117 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL))
118     CRYPTO_ctr128_encrypt(indata, out_txt,
119                           inlen, aes_key, iv, ctr, &blk_ofs, (block128_f) AES_encrypt);
120 #else
121     AES_ctr128_encrypt(indata, out_txt,
122                        inlen, aes_key, iv, ctr, &blk_ofs);
123 #endif
124     return 0;
125 }
126 
127 /*
128 * Password-based Key Derivation Function
129 */
crysprOpenSSL_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)130 int crysprOpenSSL_KmPbkdf2(
131     CRYSPR_cb *cryspr_cb,
132     char *passwd,           /* passphrase */
133     size_t passwd_len,      /* passphrase len */
134     unsigned char *salt,    /* salt */
135     size_t salt_len,        /* salt_len */
136     int itr,                /* iterations */
137     size_t key_len,         /* key_len */
138     unsigned char *out)     /* derived key */
139 {
140     (void)cryspr_cb;
141     int rc = PKCS5_PBKDF2_HMAC_SHA1(passwd,passwd_len,salt,salt_len,itr,key_len,out);
142     return(rc == 1? 0 : -1);
143 }
144 
145 #if CRYSPR_HAS_AESKWRAP
crysprOpenSSL_KmWrap(CRYSPR_cb * cryspr_cb,unsigned char * wrap,const unsigned char * sek,unsigned int seklen)146 int crysprOpenSSL_KmWrap(CRYSPR_cb *cryspr_cb,
147 		unsigned char *wrap,
148 		const unsigned char *sek,
149         unsigned int seklen)
150 {
151     crysprOpenSSL_cb *aes_data = (crysprOpenSSL_cb *)cryspr_cb;
152     AES_KEY *kek = &aes_data->ccb.aes_kek; //key encrypting key
153 
154     return(((seklen + HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_wrap_key(kek, NULL, wrap, sek, seklen)) ? 0 : -1);
155 }
156 
crysprOpenSSL_KmUnwrap(CRYSPR_cb * cryspr_cb,unsigned char * sek,const unsigned char * wrap,unsigned int wraplen)157 int crysprOpenSSL_KmUnwrap(
158         CRYSPR_cb *cryspr_cb,
159 		unsigned char *sek,             //Stream encrypting key
160 		const unsigned char *wrap,
161         unsigned int wraplen)
162 {
163     crysprOpenSSL_cb *aes_data = (crysprOpenSSL_cb *)cryspr_cb;
164     AES_KEY *kek = &aes_data->ccb.aes_kek; //key encrypting key
165 
166     return(((wraplen - HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_unwrap_key(kek, NULL, sek, wrap, wraplen)) ? 0 : -1);
167 }
168 #endif /*CRYSPR_HAS_AESKWRAP*/
169 
170 
171 static CRYSPR_methods crysprOpenSSL_methods;
172 
crysprOpenSSL(void)173 CRYSPR_methods *crysprOpenSSL(void)
174 {
175     if(NULL == crysprOpenSSL_methods.open) {
176         crysprInit(&crysprOpenSSL_methods);    //Default/fallback methods
177 
178         crysprOpenSSL_methods.prng           = crysprOpenSSL_Prng;
179     //--CryptoLib Primitive API-----------------------------------------------
180         crysprOpenSSL_methods.aes_set_key    = crysprOpenSSL_AES_SetKey;
181     #if CRYSPR_HAS_AESCTR
182         crysprOpenSSL_methods.aes_ctr_cipher = crysprOpenSSL_AES_CtrCipher;
183     #endif
184     #if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP)
185         /* AES-ECB only required if cryspr has no AES-CTR and no AES KeyWrap */
186         /* OpenSSL has both AESCTR and AESKWRP and the AESECB wrapper is only used
187            to test the falback methods */
188         crysprOpenSSL_methods.aes_ecb_cipher = crysprOpenSSL_AES_EcbCipher;
189     #endif
190     #if !CRYSPR_HAS_PBKDF2
191         crysprOpenSSL_methods.sha1_msg_digest= NULL; //Required to use eventual default/fallback KmPbkdf2
192     #endif
193 
194     //--Crypto Session API-----------------------------------------
195     //  crysprOpenSSL_methods.open     =
196     //  crysprOpenSSL_methods.close    =
197     //--Keying material (km) encryption
198 
199 #if CRYSPR_HAS_PBKDF2
200     	crysprOpenSSL_methods.km_pbkdf2  = crysprOpenSSL_KmPbkdf2;
201 #else
202 #error  There is no default/fallback method for PBKDF2
203 #endif
204     //	crysprOpenSSL_methods.km_setkey  =
205 #if CRYSPR_HAS_AESKWRAP
206         crysprOpenSSL_methods.km_wrap    = crysprOpenSSL_KmWrap;
207         crysprOpenSSL_methods.km_unwrap  = crysprOpenSSL_KmUnwrap;
208 #endif
209 
210     //--Media stream (ms) encryption
211     //  crysprOpenSSL_methods.ms_setkey  =
212     //	crysprOpenSSL_methods.ms_encrypt =
213     //	crysprOpenSSL_methods.ms_decrypt =
214     }
215     return(&crysprOpenSSL_methods);
216 }
217 
218 
219