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