@@ -497,6 +497,24 @@ _hacl_convert_errno(hacl_errno_t code, PyObject *algorithm)
497497 }
498498}
499499
500+ /*
501+ * Return a new HACL* internal state or return NULL on failure.
502+ *
503+ * An appropriate exception is set if the state cannot be created.
504+ */
505+ static HACL_HMAC_state *
506+ _hacl_hmac_state_new (HMAC_Hash_Kind kind , uint8_t * key , uint32_t len )
507+ {
508+ assert (kind != Py_hmac_kind_hash_unknown );
509+ HACL_HMAC_state * state = NULL ;
510+ hacl_errno_t retcode = Hacl_Streaming_HMAC_malloc_ (kind , key , len , & state );
511+ if (_hacl_convert_errno (retcode , NULL ) < 0 ) {
512+ assert (state == NULL );
513+ return NULL ;
514+ }
515+ return state ;
516+ }
517+
500518/*
501519 * Free the HACL* internal state.
502520 */
@@ -657,6 +675,164 @@ has_uint32_t_buffer_length(const Py_buffer *buffer)
657675
658676// --- HMAC object ------------------------------------------------------------
659677
678+ /*
679+ * Use the HMAC information 'info' to populate the corresponding fields.
680+ *
681+ * The real 'kind' for BLAKE-2 is obtained once and depends on both static
682+ * capabilities (supported compiler flags) and runtime CPUID features.
683+ */
684+ static void
685+ hmac_set_hinfo (hmacmodule_state * state ,
686+ HMACObject * self , const py_hmac_hinfo * info )
687+ {
688+ assert (info -> display_name != NULL );
689+ self -> name = Py_NewRef (info -> display_name );
690+ assert_is_static_hmac_hash_kind (info -> kind );
691+ self -> kind = narrow_hmac_hash_kind (state , info -> kind );
692+ assert (info -> block_size <= Py_hmac_hash_max_block_size );
693+ self -> block_size = info -> block_size ;
694+ assert (info -> digest_size <= Py_hmac_hash_max_digest_size );
695+ self -> digest_size = info -> digest_size ;
696+ assert (info -> api .compute != NULL );
697+ assert (info -> api .compute_py != NULL );
698+ self -> api = info -> api ;
699+ }
700+
701+ /*
702+ * Create initial HACL* internal state with the given key.
703+ *
704+ * This function MUST only be called by the HMAC object constructor
705+ * and after hmac_set_hinfo() has been called, lest the behaviour is
706+ * undefined.
707+ *
708+ * Return 0 on success and -1 on failure.
709+ */
710+ static int
711+ hmac_new_initial_state (HMACObject * self , uint8_t * key , Py_ssize_t len )
712+ {
713+ assert (key != NULL );
714+ #ifdef Py_HMAC_SSIZE_LARGER_THAN_UINT32
715+ // Technically speaking, we could hash the key to make it small
716+ // but it would require to call the hash functions ourselves and
717+ // not rely on HACL* implementation anymore. As such, we explicitly
718+ // reject keys that do not fit on 32 bits until HACL* handles them.
719+ if (len > UINT32_MAX_AS_SSIZE_T ) {
720+ PyErr_SetString (PyExc_OverflowError , INVALID_KEY_LENGTH );
721+ return -1 ;
722+ }
723+ #endif
724+ assert (self -> kind != Py_hmac_kind_hash_unknown );
725+ // _hacl_hmac_state_new() may set an exception on error
726+ self -> state = _hacl_hmac_state_new (self -> kind , key , len );
727+ return self -> state == NULL ? -1 : 0 ;
728+ }
729+
730+ /*
731+ * Feed initial data.
732+ *
733+ * This function MUST only be called by the HMAC object constructor
734+ * and after hmac_set_hinfo() and hmac_new_initial_state() have been
735+ * called, lest the behaviour is undefined.
736+ *
737+ * Return 0 on success and -1 on failure.
738+ */
739+ static int
740+ hmac_feed_initial_data (HMACObject * self , uint8_t * msg , Py_ssize_t len )
741+ {
742+ assert (self -> name != NULL );
743+ assert (self -> state != NULL );
744+ if (len == 0 ) {
745+ // do nothing if the buffer is empty
746+ return 0 ;
747+ }
748+
749+ if (len < HASHLIB_GIL_MINSIZE ) {
750+ Py_HMAC_HACL_UPDATE (self -> state , msg , len , self -> name , return - 1 );
751+ return 0 ;
752+ }
753+
754+ int res = 0 ;
755+ Py_BEGIN_ALLOW_THREADS
756+ Py_HMAC_HACL_UPDATE (self -> state , msg , len , self -> name , goto error );
757+ goto done ;
758+ #ifndef NDEBUG
759+ error :
760+ res = -1 ;
761+ #else
762+ Py_UNREACHABLE ();
763+ #endif
764+ done :
765+ Py_END_ALLOW_THREADS
766+ return res ;
767+ }
768+
769+ /*[clinic input]
770+ _hmac.new
771+
772+ key as keyobj: object
773+ msg as msgobj: object(c_default="NULL") = None
774+ digestmod as hash_info_ref: object(c_default="NULL") = None
775+
776+ Return a new HMAC object.
777+ [clinic start generated code]*/
778+
779+ static PyObject *
780+ _hmac_new_impl (PyObject * module , PyObject * keyobj , PyObject * msgobj ,
781+ PyObject * hash_info_ref )
782+ /*[clinic end generated code: output=7c7573a427d58758 input=92fc7c0a00707d42]*/
783+ {
784+ hmacmodule_state * state = get_hmacmodule_state (module );
785+ if (hash_info_ref == NULL ) {
786+ PyErr_SetString (PyExc_TypeError ,
787+ "new() missing 1 required argument 'digestmod'" );
788+ return NULL ;
789+ }
790+
791+ const py_hmac_hinfo * info = find_hash_info (state , hash_info_ref );
792+ if (info == NULL ) {
793+ return NULL ;
794+ }
795+
796+ HMACObject * self = PyObject_GC_New (HMACObject , state -> hmac_type );
797+ if (self == NULL ) {
798+ return NULL ;
799+ }
800+ HASHLIB_INIT_MUTEX (self );
801+ hmac_set_hinfo (state , self , info );
802+ int rc ;
803+ // Create the HACL* internal state with the given key.
804+ Py_buffer key ;
805+ GET_BUFFER_VIEW_OR_ERROR (keyobj , & key , goto error_on_key );
806+ rc = hmac_new_initial_state (self , key .buf , key .len );
807+ PyBuffer_Release (& key );
808+ if (rc < 0 ) {
809+ goto error ;
810+ }
811+ // Feed the internal state the initial message if any.
812+ if (msgobj != NULL && msgobj != Py_None ) {
813+ Py_buffer msg ;
814+ GET_BUFFER_VIEW_OR_ERROR (msgobj , & msg , goto error );
815+ rc = hmac_feed_initial_data (self , msg .buf , msg .len );
816+ PyBuffer_Release (& msg );
817+ #ifndef NDEBUG
818+ if (rc < 0 ) {
819+ goto error ;
820+ }
821+ #else
822+ (void )rc ;
823+ #endif
824+ }
825+ assert (rc == 0 );
826+ PyObject_GC_Track (self );
827+ return (PyObject * )self ;
828+
829+ error_on_key :
830+ self -> state = NULL ;
831+ error :
832+ Py_DECREF (self );
833+ return NULL ;
834+ }
835+
660836/*
661837 * Copy HMAC hash information from 'src' to 'out'.
662838 */
@@ -1240,6 +1416,7 @@ _hmac_compute_blake2b_32_impl(PyObject *module, PyObject *key, PyObject *msg)
12401416// --- HMAC module methods ----------------------------------------------------
12411417
12421418static PyMethodDef hmacmodule_methods [] = {
1419+ _HMAC_NEW_METHODDEF
12431420 /* one-shot dispatcher */
12441421 _HMAC_COMPUTE_DIGEST_METHODDEF
12451422 /* one-shot methods */
0 commit comments