66#if SKEY_SUPPORT == 1
77
88#include "cipher.h"
9- #include <string.h>
109#include "openssl/prov_ssl.h"
10+ #include "openssl/rand.h"
11+ #include <string.h>
12+
13+ #define MAX_PADDING 256;
14+ #define AESBLOCK 16 /* 128 bits for all AES modes */
1115
1216DISPATCH_CIPHER_FN (cipher , freectx );
1317DISPATCH_CIPHER_FN (aes , dupctx );
@@ -35,6 +39,14 @@ struct p11prov_cipher_ctx {
3539 CK_FLAGS operation ;
3640
3741 P11PROV_SESSION * session ;
42+
43+ /* OpenSSL violates layering separation and decided
44+ * to process AES CBC MAC/padding handling in TLS 1.x < 1.3
45+ * in the lower cipher layer, so we have to do it here as well
46+ * for compatibility ... */
47+ unsigned int tlsver ;
48+ size_t tlsmacsize ;
49+ unsigned char * tlsmac ;
3850};
3951
4052static void * p11prov_cipher_newctx (void * provctx , int size , CK_ULONG mechanism )
@@ -157,7 +169,7 @@ static int p11prov_aes_get_params(OSSL_PARAM params[], int size, int mode,
157169 int ciph_mode = 0 ;
158170 int flags = mode & MODE_flags_mask ;
159171 size_t keysize = size / 8 ;
160- size_t blocksize = 16 ; /* 128 bits for all AES modes */
172+ size_t blocksize = AESBLOCK ;
161173 size_t ivsize = 16 ; /* 128 bits for all modes but ECB */
162174
163175 switch (mode & MODE_modes_mask ) {
@@ -200,6 +212,7 @@ static void p11prov_cipher_freectx(void *ctx)
200212 p11prov_obj_free (cctx -> key );
201213 p11prov_return_session (cctx -> session );
202214 OPENSSL_clear_free (cctx -> mech .pParameter , cctx -> mech .ulParameterLen );
215+ OPENSSL_clear_free (cctx -> tlsmac , cctx -> tlsmacsize );
203216 OPENSSL_clear_free (cctx , sizeof (struct p11prov_cipher_ctx ));
204217}
205218
@@ -330,6 +343,12 @@ static CK_RV p11prov_cipher_session_init(struct p11prov_cipher_ctx *cctx)
330343 return CKR_SLOT_ID_INVALID ;
331344 }
332345
346+ if (cctx -> tlsver != 0 && cctx -> mech .mechanism == CKM_AES_CBC_PAD ) {
347+ /* In the special TLS mode we handle de-padding and mac extraction
348+ * outside the pkcs11 module to conform to what OpenSSL does */
349+ cctx -> mech .mechanism = CKM_AES_CBC ;
350+ }
351+
333352 rv = p11prov_get_session (cctx -> provctx , & slotid , NULL , NULL ,
334353 cctx -> mech .mechanism , NULL , NULL , true, false,
335354 & cctx -> session );
@@ -447,32 +466,210 @@ static int p11prov_cipher_decrypt_skey_init(void *ctx, void *keydata,
447466 return RET_OSSL_OK ;
448467}
449468
469+ /* This function needs to be executed in constant time */
470+ static CK_RV tlsunpad (struct p11prov_cipher_ctx * cctx , unsigned char * out ,
471+ CK_ULONG inlen , CK_ULONG * outlen )
472+ {
473+ CK_RV rv = CKR_GENERAL_ERROR ;
474+ CK_ULONG overhead = cctx -> tlsmacsize + 1 ; /* mac size + padlen byte */
475+ CK_ULONG maxcheck = MAX_PADDING ;
476+ CK_ULONG padsize = out [inlen - 1 ];
477+ CK_ULONG olen = inlen ;
478+ CK_ULONG pass ;
479+
480+ /* Remove explicit IV for TLS 1.1 and 1.2 */
481+ if (cctx -> tlsver != 0x301 ) {
482+ /* This is a bad interface as it make it seem that
483+ * the returned output buffer is incorrectly pointing
484+ * at the IV and not the data, but OpenSSL will in turn
485+ * offset the buffer later, based on knoledge that this
486+ * cipher return a length that excludes the IV from the
487+ * count. */
488+ out += AESBLOCK ;
489+ olen = inlen - AESBLOCK ;
490+ }
491+
492+ /* olen is public known so can be checked normally */
493+ if (olen < overhead ) {
494+ return CKR_BUFFER_TOO_SMALL ;
495+ }
496+
497+ if (olen < cctx -> tlsmacsize ) {
498+ return CKR_BUFFER_TOO_SMALL ;
499+ }
500+
501+ if (maxcheck > olen ) {
502+ maxcheck = olen ;
503+ }
504+
505+ /* olen must not be smaller than padsize + overhead */
506+ pass = ~constant_smaller_mask (olen , overhead + padsize );
507+
508+ /* creates a mask so that we check only the padding bytes
509+ * without revealing the padding length in a conditional.
510+ * mask is 0xff when i < padsize, and 0 otherwise, allowing
511+ * us to scan the whole buffer while really only testing for
512+ * equality only the padding part, as the xoring with non-pad
513+ * data is ignored my the empty mask. We skip checking the
514+ * last value itself as that is always == padsize */
515+ for (int i = 0 ; i < maxcheck - 1 ; i ++ ) {
516+ unsigned char mask = constant_smaller_mask (i , padsize );
517+ unsigned char data = out [olen - i - 2 ];
518+
519+ pass &= ~(mask & (padsize ^ data ));
520+ }
521+
522+ /* renormalize to a CK_ULONG */
523+ pass = constant_equal_mask (pass , 0xff );
524+
525+ if (cctx -> tlsmacsize > 0 ) {
526+ unsigned char randmac [EVP_MAX_MD_SIZE ];
527+ size_t mac_pos = olen - cctx -> tlsmacsize - (pass & (padsize + 1 ));
528+ size_t mac_area = 0 ;
529+ int err = RET_OSSL_ERR ;
530+
531+ /* allocate space for the mac */
532+ cctx -> tlsmac = OPENSSL_zalloc (cctx -> tlsmacsize );
533+ if (!cctx -> tlsmac ) {
534+ return CKR_GENERAL_ERROR ;
535+ }
536+
537+ /* random mac we return if something is wrong */
538+ err = RAND_bytes_ex (p11prov_ctx_get_libctx (cctx -> provctx ), randmac ,
539+ sizeof (randmac ), 0 );
540+ if (err != RET_OSSL_OK ) {
541+ return CKR_GENERAL_ERROR ;
542+ }
543+
544+ /* olen and mac size are public data, so we can do this
545+ * assignment without bothering with constant time */
546+ if (olen > cctx -> tlsmacsize + 256 ) {
547+ mac_area = olen - cctx -> tlsmacsize - 256 ;
548+ }
549+
550+ for (size_t i = mac_area ; i < olen ; i ++ ) {
551+ for (int j = 0 ; j < cctx -> tlsmacsize ; j ++ ) {
552+ unsigned char mask =
553+ ~constant_smaller_mask (i , mac_pos )
554+ & constant_smaller_mask (i , mac_pos + cctx -> tlsmacsize )
555+ & constant_equal_mask (i , j + mac_pos );
556+ cctx -> tlsmac [j ] |= out [i ] & mask ;
557+ }
558+ }
559+
560+ /* on depadding failure overwrite with random data */
561+ for (int j = 0 ; j < cctx -> tlsmacsize ; j ++ ) {
562+ cctx -> tlsmac [j ] =
563+ constant_select_byte_mask (cctx -> tlsmac [j ], randmac [j ], pass );
564+ }
565+
566+ rv = CKR_OK ;
567+ } else {
568+ /* no MAC to check just return the result */
569+ if (pass + 1 == 0 ) {
570+ rv = CKR_OK ;
571+ }
572+ }
573+
574+ * outlen = olen - cctx -> tlsmacsize - (pass & (padsize + 1 ));
575+ return rv ;
576+ }
577+
450578static int p11prov_cipher_update (void * ctx , unsigned char * out , size_t * outl ,
451579 size_t outsize , const unsigned char * in ,
452580 size_t inl )
453581{
454582 struct p11prov_cipher_ctx * cctx = (struct p11prov_cipher_ctx * )ctx ;
583+ CK_SESSION_HANDLE session_handle ;
455584 CK_ULONG outlen = outsize ;
456585 CK_ULONG inlen = inl ;
457586 CK_RV rv ;
458587
588+ if (cctx -> tlsver != 0 ) {
589+ /* Special OpenSSL layering violating mode.
590+ * A single update is a full record.
591+ * Inputs need to be consistent with stricter requirements */
592+ if (!in || in != out || outsize < inl || !cctx -> pad ) {
593+ ERR_raise (ERR_LIB_PROV , PROV_R_CIPHER_OPERATION_FAILED );
594+ return 0 ;
595+ }
596+ }
597+
459598 if (!cctx -> session ) {
460599 rv = p11prov_cipher_session_init (cctx );
461600 if (rv != CKR_OK ) {
462601 return RET_OSSL_ERR ;
463602 }
464603 }
604+ session_handle = p11prov_session_handle (cctx -> session );
465605
466606 switch (cctx -> operation ) {
467607 case CKF_ENCRYPT :
468- rv = p11prov_EncryptUpdate (cctx -> provctx ,
469- p11prov_session_handle (cctx -> session ),
470- (void * )in , inlen , out , & outlen );
608+ if (cctx -> tlsver != 0 ) {
609+ /* Custom handle padding */
610+ size_t padsize = AESBLOCK - (inl % AESBLOCK );
611+ unsigned char padval = (unsigned char )(padsize - 1 );
612+
613+ if (outsize < inl + padsize ) {
614+ rv = CKR_BUFFER_TOO_SMALL ;
615+ P11PROV_raise (cctx -> provctx , rv , "Output buffer too small" );
616+ return RET_OSSL_ERR ;
617+ }
618+ inlen += padsize ;
619+ if ((inlen % AESBLOCK ) != 0 ) {
620+ rv = CKR_ARGUMENTS_BAD ;
621+ P11PROV_raise (cctx -> provctx , rv , "Invalid input buffer size" );
622+ return RET_OSSL_ERR ;
623+ }
624+ /* add the padding, relies on in == out and therefore enough
625+ * space available in the buffer */
626+ memset (& out [inl ], padval , padsize );
627+
628+ /* in TLS mode we must use signle shot decryption to properly
629+ * auto-finalize the session as OpenSSL won't */
630+ rv = p11prov_Encrypt (cctx -> provctx , session_handle , (void * )in ,
631+ inlen , out , & outlen );
632+
633+ /* unconditionally return the session */
634+ p11prov_return_session (cctx -> session );
635+ cctx -> session = NULL ;
636+ } else {
637+ rv = p11prov_EncryptUpdate (cctx -> provctx , session_handle ,
638+ (void * )in , inlen , out , & outlen );
639+ }
471640 break ;
472641 case CKF_DECRYPT :
473- rv = p11prov_DecryptUpdate (cctx -> provctx ,
474- p11prov_session_handle (cctx -> session ),
475- (void * )in , inlen , out , & outlen );
642+ if (cctx -> tlsver != 0 ) {
643+ if ((inlen % AESBLOCK ) != 0 ) {
644+ rv = CKR_ARGUMENTS_BAD ;
645+ P11PROV_raise (cctx -> provctx , rv , "Invalid input buffer size" );
646+ return RET_OSSL_ERR ;
647+ }
648+ /* in TLS mode we must use signle shot decryption to properly
649+ * auto-finalize the session as OpenSSL won't */
650+ rv = p11prov_Decrypt (cctx -> provctx , session_handle , (void * )in ,
651+ inlen , out , & outlen );
652+
653+ /* unconditionally return the session */
654+ p11prov_return_session (cctx -> session );
655+ cctx -> session = NULL ;
656+
657+ if (rv != CKR_OK ) {
658+ P11PROV_raise (cctx -> provctx , rv , "Decryption failure" );
659+ return RET_OSSL_ERR ;
660+ }
661+ /* remove padding and fill in tlsmac as needed */
662+ if (cctx -> tlsmac ) {
663+ OPENSSL_clear_free (cctx -> tlsmac , cctx -> tlsmacsize );
664+ cctx -> tlsmac = NULL ;
665+ }
666+
667+ /* Assumes inlen = outlen on correct decryption */
668+ rv = tlsunpad (cctx , out , inlen , & outlen );
669+ } else {
670+ rv = p11prov_DecryptUpdate (cctx -> provctx , session_handle ,
671+ (void * )in , inlen , out , & outlen );
672+ }
476673 break ;
477674 default :
478675 rv = CKR_GENERAL_ERROR ;
@@ -604,9 +801,11 @@ static int p11prov_aes_get_ctx_params(void *ctx, OSSL_PARAM params[])
604801
605802 p = OSSL_PARAM_locate (params , OSSL_CIPHER_PARAM_TLS_MAC );
606803 if (p ) {
607- /* TODO: ? (octet_ptr) */
608- ERR_raise (ERR_LIB_PROV , PROV_R_FAILED_TO_SET_PARAMETER );
609- return RET_OSSL_ERR ;
804+ ret = OSSL_PARAM_set_octet_ptr (p , cctx -> tlsmac , cctx -> tlsmacsize );
805+ if (ret != RET_OSSL_OK ) {
806+ ERR_raise (ERR_LIB_PROV , PROV_R_FAILED_TO_SET_PARAMETER );
807+ return RET_OSSL_ERR ;
808+ }
610809 }
611810
612811 return RET_OSSL_OK ;
@@ -679,6 +878,43 @@ static int p11prov_aes_set_ctx_params(void *vctx, const OSSL_PARAM params[])
679878 }
680879 }
681880
881+ p = OSSL_PARAM_locate_const (params , OSSL_CIPHER_PARAM_TLS_VERSION );
882+ if (p ) {
883+ CK_RV rv = CKR_MECHANISM_PARAM_INVALID ;
884+ unsigned int version ;
885+ int ret = OSSL_PARAM_get_uint (p , & version );
886+ if (ret != RET_OSSL_OK ) {
887+ P11PROV_raise (ctx -> provctx , rv , "Invalid TLS Version parameter" );
888+ return RET_OSSL_ERR ;
889+ }
890+ switch (version ) {
891+ case 0x301 : /* TLS 1.0 */
892+ case 0x302 : /* TLS 1.1 */
893+ case 0x303 : /* TLS 1.2 */
894+ ctx -> tlsver = version ;
895+ break ;
896+ default :
897+ P11PROV_raise (ctx -> provctx , rv , "Unsupported TLS Version" );
898+ return RET_OSSL_ERR ;
899+ }
900+ }
901+
902+ p = OSSL_PARAM_locate_const (params , OSSL_CIPHER_PARAM_TLS_MAC_SIZE );
903+ if (p ) {
904+ CK_RV rv = CKR_MECHANISM_PARAM_INVALID ;
905+ size_t macsize ;
906+ int ret = OSSL_PARAM_get_size_t (p , & macsize );
907+ if (ret != RET_OSSL_OK ) {
908+ P11PROV_raise (ctx -> provctx , rv , "Invalid TLS MAC Size parameter" );
909+ return RET_OSSL_ERR ;
910+ }
911+ if (macsize > EVP_MAX_MD_SIZE ) {
912+ P11PROV_raise (ctx -> provctx , rv , "Invalid TLS Mac Size" );
913+ return RET_OSSL_ERR ;
914+ }
915+ ctx -> tlsmacsize = macsize ;
916+ }
917+
682918 return RET_OSSL_OK ;
683919}
684920
@@ -689,9 +925,7 @@ static const OSSL_PARAM p11prov_aes_generic_gettable_ctx_params[] = {
689925 OSSL_PARAM_uint (OSSL_CIPHER_PARAM_NUM , NULL ),
690926 OSSL_PARAM_octet_string (OSSL_CIPHER_PARAM_IV , NULL , 0 ),
691927 OSSL_PARAM_octet_string (OSSL_CIPHER_PARAM_UPDATED_IV , NULL , 0 ),
692- /* Supported by OpenSSL but not here yet
693- * OSSL_CIPHER_PARAM_TLS_MAC
694- */
928+ OSSL_PARAM_octet_string (OSSL_CIPHER_PARAM_TLS_MAC , NULL , 0 ),
695929 OSSL_PARAM_END
696930};
697931
@@ -729,12 +963,12 @@ static const OSSL_PARAM *p11prov_aes_gettable_ctx_params(void *vctx,
729963/* Supported by OpenSSL but not here:
730964 * OSSL_CIPHER_PARAM_NUM (uint)
731965 * OSSL_CIPHER_PARAM_USE_BITS (uint)
732- * OSSL_CIPHER_PARAM_TLS_VERSION (uint)
733- * OSSL_CIPHER_PARAM_TLS_MAC_SIZE (size_t)
734966 */
735967
736968static const OSSL_PARAM p11prov_aes_generic_settable_ctx_params [] = {
737- GENERIC_SETTABLE_CTX_PARAMS (), OSSL_PARAM_END
969+ GENERIC_SETTABLE_CTX_PARAMS (),
970+ OSSL_PARAM_uint (OSSL_CIPHER_PARAM_TLS_VERSION , NULL ),
971+ OSSL_PARAM_size_t (OSSL_CIPHER_PARAM_TLS_MAC_SIZE , NULL ), OSSL_PARAM_END
738972};
739973
740974static const OSSL_PARAM p11prov_aes_cts_settable_ctx_params [] = {
0 commit comments