/**
 * PostgreSQL Database Management System
 * (formerly known as Postgres, then as Postgres95)
 *
 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
 *
 * Portions Copyright (c) 1994, The Regents of the University of California
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without a written agreement
 * is hereby granted, provided that the above copyright notice and this
 * paragraph and the following two paragraphs appear in all copies.
 *
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
 * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
 * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */
#pragma once

#include <stdint.h>
#include <stddef.h>

#include "box/authentication.h" /* for AUTH_SALT_SIZE */

enum {
	/* len of a buffer used by md5 hash context. */
	MD5_BUFLEN = 64,
	/* Size of result generated by MD5 computation */
	MD5_DIGEST_LENGTH = 16,
	/**
	 * Length of a buffer that can store a password hashed by md5 algorithm.
	 * "md5" + 32-hex-digit MD5 checksum.
	 */
	MD5_PASSWD_LEN = 3 + 32,
	/** length of salt sent to remote side. */
	MD5_SALT_LEN = 4
};

/** Allowed symbols set in md5 checksum. */
#define MD5_PASSWD_CHARSET "0123456789abcdef"

static_assert((int)MD5_SALT_LEN <= (int)AUTH_SALT_SIZE,
	      "MD5 password salt is too big");

/* Context data for MD5 */
struct md5_ctx {
	/** Current md5 state. */
	union {
		uint32_t md5_state32[4];
		uint8_t md5_state8[16];
	} md5_st;

	/** md5 counter */
	union {
		/** counter as a 64-bit integer */
		uint64_t md5_count64;
		/** counter as an array of 1-byte integers */
		uint8_t md5_count8[8];
	} md5_count;

	/** processed len of the buffer */
	unsigned int md5_i;
	uint8_t md5_buf[MD5_BUFLEN];
};

/** Initialize a MD5 context. */
void
md5_init(struct md5_ctx *ctx);

/** Update a MD5 context. */
void
md5_update(struct md5_ctx *ctx, const uint8_t *data, size_t len);

/** Finalize a MD5 context. */
void
md5_final(struct md5_ctx *ctx, uint8_t *dest);
