@@ -590,6 +590,79 @@ has_uint32_t_buffer_length(const Py_buffer *buffer)
590590
591591// --- HMAC object ------------------------------------------------------------
592592
593+ /*
594+ * Copy HMAC hash information from 'src' to 'out'.
595+ */
596+ static void
597+ hmac_copy_hinfo (HMACObject * out , const HMACObject * src )
598+ {
599+ assert (src -> name != NULL );
600+ out -> name = Py_NewRef (src -> name );
601+ assert (src -> kind != Py_hmac_kind_hash_unknown );
602+ out -> kind = src -> kind ;
603+ assert (src -> block_size <= Py_hmac_hash_max_block_size );
604+ out -> block_size = src -> block_size ;
605+ assert (src -> digest_size <= Py_hmac_hash_max_digest_size );
606+ out -> digest_size = src -> digest_size ;
607+ assert (src -> api .compute != NULL );
608+ assert (src -> api .compute_py != NULL );
609+ out -> api = src -> api ;
610+ }
611+
612+ /*
613+ * Copy the HMAC internal state from 'src' to 'out'.
614+ *
615+ * The internal state of 'out' must not already exist.
616+ *
617+ * Return 0 on success and -1 on failure.
618+ */
619+ static int
620+ hmac_copy_state (HMACObject * out , const HMACObject * src )
621+ {
622+ assert (src -> state != NULL );
623+ out -> state = Hacl_Streaming_HMAC_copy (src -> state );
624+ if (out -> state == NULL ) {
625+ PyErr_NoMemory ();
626+ return -1 ;
627+ }
628+ return 0 ;
629+ }
630+
631+ /*[clinic input]
632+ _hmac.HMAC.copy
633+
634+ cls: defining_class
635+
636+ Return a copy ("clone") of the HMAC object.
637+ [clinic start generated code]*/
638+
639+ static PyObject *
640+ _hmac_HMAC_copy_impl (HMACObject * self , PyTypeObject * cls )
641+ /*[clinic end generated code: output=a955bfa55b65b215 input=17b2c0ad0b147e36]*/
642+ {
643+ hmacmodule_state * state = get_hmacmodule_state_by_cls (cls );
644+ HMACObject * copy = PyObject_GC_New (HMACObject , state -> hmac_type );
645+ if (copy == NULL ) {
646+ return NULL ;
647+ }
648+
649+ ENTER_HASHLIB (self );
650+ /* copy hash information */
651+ hmac_copy_hinfo (copy , self );
652+ /* copy internal state */
653+ int rc = hmac_copy_state (copy , self );
654+ LEAVE_HASHLIB (self );
655+
656+ if (rc < 0 ) {
657+ Py_DECREF (copy );
658+ return NULL ;
659+ }
660+
661+ HASHLIB_INIT_MUTEX (copy );
662+ PyObject_GC_Track (copy );
663+ return (PyObject * )copy ;
664+ }
665+
593666/*
594667 * Update the HMAC object with the given buffer.
595668 *
@@ -806,6 +879,7 @@ HMACObject_traverse(PyObject *op, visitproc visit, void *arg)
806879}
807880
808881static PyMethodDef HMACObject_methods [] = {
882+ _HMAC_HMAC_COPY_METHODDEF
809883 _HMAC_HMAC_UPDATE_METHODDEF
810884 _HMAC_HMAC_DIGEST_METHODDEF
811885 _HMAC_HMAC_HEXDIGEST_METHODDEF
0 commit comments