Amazon Kinesis Webrtc C SDK
 
Loading...
Searching...
No Matches
Crypto.h
Go to the documentation of this file.
1#ifndef __KINESIS_VIDEO_WEBRTC_CLIENT_CRYPTO_CRYPTO__
2#define __KINESIS_VIDEO_WEBRTC_CLIENT_CRYPTO_CRYPTO__
3
4#pragma once
5
6#ifdef __cplusplus
7extern "C" {
8#endif
9
10#ifdef KVS_USE_OPENSSL
11#include <openssl/opensslv.h>
12
13/*
14 * OpenSSL 3.x compatibility macros.
15 * The deprecated 1.1.x APIs still work in 3.x but will be removed in 4.0.
16 * When OPENSSL_VERSION_NUMBER >= 0x30000000L, use the modern EVP-based APIs.
17 */
18
19/* SSL_get_peer_certificate was renamed to SSL_get1_peer_certificate in 3.0 */
20#if OPENSSL_VERSION_NUMBER >= 0x30000000L
21#define KVS_SSL_GET_PEER_CERTIFICATE(ssl) SSL_get1_peer_certificate(ssl)
22#else
23#define KVS_SSL_GET_PEER_CERTIFICATE(ssl) SSL_get_peer_certificate(ssl)
24#endif
25
26#define KVS_RSA_F4 RSA_F4
27#define KVS_MD5_DIGEST_LENGTH MD5_DIGEST_LENGTH
28#define KVS_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
29
30/* MD5 one-shot: MD5() removed in OpenSSL 3.x, use EVP_Q_digest */
31#if OPENSSL_VERSION_NUMBER >= 0x30000000L
32#define KVS_MD5_DIGEST(m, mlen, ob) EVP_Q_digest(NULL, "MD5", NULL, (m), (mlen), (ob), NULL);
33#else
34#define KVS_MD5_DIGEST(m, mlen, ob) MD5((m), (mlen), (ob));
35#endif
36
37/* HMAC one-shot: HMAC() deprecated in OpenSSL 3.x, use kvsSha1Hmac() function with proper cleanup */
38#if OPENSSL_VERSION_NUMBER >= 0x30000000L
39STATUS kvsSha1Hmac(const PBYTE pKey, size_t keyLen, const PBYTE pMessage, size_t messageLen, PBYTE pOutput, PUINT32 pOutputLen);
40#define KVS_SHA1_HMAC(k, klen, m, mlen, ob, plen) \
41 CHK_STATUS(kvsSha1Hmac((const PBYTE)(k), (size_t) (klen), (const PBYTE)(m), (size_t) (mlen), (ob), (plen)));
42#else
43#define KVS_SHA1_HMAC(k, klen, m, mlen, ob, plen) \
44 CHK(NULL != HMAC(EVP_sha1(), (k), (INT32) (klen), (m), (mlen), (ob), (plen)), STATUS_HMAC_GENERATION_ERROR);
45#endif
46
47/*
48 * KVS_CRYPTO_INIT: On OpenSSL 1.1.0+, the library auto-initializes so the legacy
49 * init calls are no-ops. On 3.x, OPENSSL_INIT_NO_ATEXIT prevents OPENSSL_cleanup()
50 * from being called by libwebsockets on context destroy, avoiding state corruption.
51 */
52#if OPENSSL_VERSION_NUMBER >= 0x30000000L
53#define KVS_CRYPTO_INIT() \
54 do { \
55 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_NO_ATEXIT, NULL); \
56 } while (0)
57#else
58#define KVS_CRYPTO_INIT() \
59 do { \
60 OpenSSL_add_ssl_algorithms(); \
61 SSL_load_error_strings(); \
62 SSL_library_init(); \
63 } while (0)
64#endif
65
66#define LOG_OPENSSL_ERROR(s) \
67 while ((sslErr = ERR_get_error()) != 0) { \
68 if (sslErr != SSL_ERROR_WANT_WRITE && sslErr != SSL_ERROR_WANT_READ) { \
69 DLOGW("%s failed with %s", (s), ERR_error_string(sslErr, NULL)); \
70 } \
71 }
72
73typedef enum {
74 KVS_SRTP_PROFILE_AES128_CM_HMAC_SHA1_80 = SRTP_AES128_CM_SHA1_80,
75 KVS_SRTP_PROFILE_AES128_CM_HMAC_SHA1_32 = SRTP_AES128_CM_SHA1_32,
76} KVS_SRTP_PROFILE;
77#elif KVS_USE_MBEDTLS
78#define KVS_RSA_F4 0x10001L
79#define KVS_MD5_DIGEST_LENGTH 16
80#define KVS_SHA1_DIGEST_LENGTH 20
81#if MBEDTLS_VERSION_MAJOR >= 4
82/* TF-PSA-Crypto 1.0 (mbedTLS 4) removed the legacy MBEDTLS_MD5_C module and the
83 * one-shot mbedtls_md5(); MD5 is reachable only through PSA (PSA_WANT_ALG_MD5). */
84#define KVS_MD5_DIGEST(m, mlen, ob) \
85 do { \
86 size_t _kvsMd5Len = 0; \
87 (void) psa_crypto_init(); \
88 (void) psa_hash_compute(PSA_ALG_MD5, (const unsigned char*) (m), (mlen), (unsigned char*) (ob), KVS_MD5_DIGEST_LENGTH, &_kvsMd5Len); \
89 } while (0);
90#elif MBEDTLS_VERSION_NUMBER >= 0x03000000
91#define KVS_MD5_DIGEST(m, mlen, ob) mbedtls_md5((m), (mlen), (ob));
92#else
93#define KVS_MD5_DIGEST(m, mlen, ob) mbedtls_md5_ret((m), (mlen), (ob));
94#endif
95#define KVS_SHA1_HMAC(k, klen, m, mlen, ob, plen) \
96 CHK(0 == mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), (k), (klen), (m), (mlen), (ob)), STATUS_HMAC_GENERATION_ERROR); \
97 *(plen) = mbedtls_md_get_size(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1));
98#if MBEDTLS_VERSION_MAJOR >= 4
99/* PSA Crypto must be initialised before any psa_* call. psa_crypto_init() is
100 * idempotent; calling it once from the SDK init path avoids the per-session
101 * race on builds without MBEDTLS_THREADING_C. */
102#define KVS_CRYPTO_INIT() \
103 do { \
104 (void) psa_crypto_init(); \
105 } while (0)
106#else
107#define KVS_CRYPTO_INIT() \
108 do { \
109 } while (0)
110#endif
111#define LOG_MBEDTLS_ERROR(s, ret) \
112 do { \
113 CHAR __mbedtlsErr[1024]; \
114 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { \
115 mbedtls_strerror(ret, __mbedtlsErr, SIZEOF(__mbedtlsErr)); \
116 DLOGW("%s failed with %s", (s), __mbedtlsErr); \
117 } \
118 } while (0)
119
120typedef enum {
121 KVS_SRTP_PROFILE_AES128_CM_HMAC_SHA1_80 = MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80,
122 KVS_SRTP_PROFILE_AES128_CM_HMAC_SHA1_32 = MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32,
123} KVS_SRTP_PROFILE;
124#else
125#error "A Crypto implementation is required."
126#endif
127
128#ifdef __cplusplus
129}
130#endif
131#endif //__KINESIS_VIDEO_WEBRTC_CLIENT_CRYPTO_CRYPTO__