secret = PORT_Alloc(len);  err = mp_to_unsigned_octets(&ZZ, secret, len); if (err >= 0) err = MP_OKAY;
DH_Derive(SECItem *publicValue,           SECItem *prime,           SECItem *privateValue,           SECItem *derivedSecret,           unsigned int maxOutBytes){    mp_int p, Xa, Yb, ZZ;    mp_err err = MP_OKAY;    unsigned int len;    if (!publicValue || !prime || !privateValue || !derivedSecret) {	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return SECFailure;    }    memset(derivedSecret, 0, sizeof *derivedSecret);    MP_DIGITS(&p)  = 0;    MP_DIGITS(&Xa) = 0;    MP_DIGITS(&Yb) = 0;    MP_DIGITS(&ZZ) = 0;    CHECK_MPI_OK( mp_init(&p)  );    CHECK_MPI_OK( mp_init(&Xa) );    CHECK_MPI_OK( mp_init(&Yb) );    CHECK_MPI_OK( mp_init(&ZZ) );    SECITEM_TO_MPINT(*publicValue,  &Yb);    SECITEM_TO_MPINT(*privateValue, &Xa);    SECITEM_TO_MPINT(*prime,        &p);    /* ZZ = (Yb)**Xa mod p */    CHECK_MPI_OK( mp_exptmod(&Yb, &Xa, &p, &ZZ) );    len = mp_unsigned_octet_size(&ZZ);    /* Take minimum of bytes requested and bytes in shared secret,    ** if maxOutBytes is 0 take all of the bytes from the prime.    */    if (maxOutBytes > 0)	len = PR_MIN(len, maxOutBytes);    /* It is the caller's responsibility to free this buffer. */    SECITEM_AllocItem(NULL, derivedSecret, len);    err = mp_to_unsigned_octets(&ZZ, derivedSecret->data, len);    if (err >= 0) err = MP_OKAY;cleanup:    mp_clear(&p);    mp_clear(&Xa);    mp_clear(&Yb);    mp_clear(&ZZ);    if (err) {	MP_TO_SEC_ERROR(err);	if (derivedSecret->data) 	    PORT_ZFree(derivedSecret->data, derivedSecret->len);	return SECFailure;    }    return SECSuccess;}