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