lib/crypto/curve25519-fiat32.c

Source file repositories/reference/linux-study-clean/lib/crypto/curve25519-fiat32.c

File Facts

System
Linux kernel
Corpus path
lib/crypto/curve25519-fiat32.c
Extension
.c
Size
30259 bytes
Lines
865
Domain
Kernel Services
Bucket
lib
Inferred role
Kernel Services: implementation source
Status
source implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0 OR MIT
/*
 * Copyright (C) 2015-2016 The fiat-crypto Authors.
 * Copyright (C) 2018-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
 *
 * This is a machine-generated formally verified implementation of Curve25519
 * ECDH from: <https://github.com/mit-plv/fiat-crypto>. Though originally
 * machine generated, it has been tweaked to be suitable for use in the kernel.
 * It is optimized for 32-bit machines and machines that cannot work efficiently
 * with 128-bit integer types.
 */

#include <linux/unaligned.h>
#include <crypto/curve25519.h>
#include <linux/string.h>

/* fe means field element. Here the field is \Z/(2^255-19). An element t,
 * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
 * t[3]+2^102 t[4]+...+2^230 t[9].
 * fe limbs are bounded by 1.125*2^26,1.125*2^25,1.125*2^26,1.125*2^25,etc.
 * Multiplication and carrying produce fe from fe_loose.
 */
typedef struct fe { u32 v[10]; } fe;

/* fe_loose limbs are bounded by 3.375*2^26,3.375*2^25,3.375*2^26,3.375*2^25,etc
 * Addition and subtraction produce fe_loose from (fe, fe).
 */
typedef struct fe_loose { u32 v[10]; } fe_loose;

static __always_inline void fe_frombytes_impl(u32 h[10], const u8 *s)
{
	/* Ignores top bit of s. */
	u32 a0 = get_unaligned_le32(s);
	u32 a1 = get_unaligned_le32(s+4);
	u32 a2 = get_unaligned_le32(s+8);
	u32 a3 = get_unaligned_le32(s+12);
	u32 a4 = get_unaligned_le32(s+16);
	u32 a5 = get_unaligned_le32(s+20);
	u32 a6 = get_unaligned_le32(s+24);
	u32 a7 = get_unaligned_le32(s+28);
	h[0] = a0&((1<<26)-1);                    /* 26 used, 32-26 left.   26 */
	h[1] = (a0>>26) | ((a1&((1<<19)-1))<< 6); /* (32-26) + 19 =  6+19 = 25 */
	h[2] = (a1>>19) | ((a2&((1<<13)-1))<<13); /* (32-19) + 13 = 13+13 = 26 */
	h[3] = (a2>>13) | ((a3&((1<< 6)-1))<<19); /* (32-13) +  6 = 19+ 6 = 25 */
	h[4] = (a3>> 6);                          /* (32- 6)              = 26 */
	h[5] = a4&((1<<25)-1);                    /*                        25 */
	h[6] = (a4>>25) | ((a5&((1<<19)-1))<< 7); /* (32-25) + 19 =  7+19 = 26 */
	h[7] = (a5>>19) | ((a6&((1<<12)-1))<<13); /* (32-19) + 12 = 13+12 = 25 */
	h[8] = (a6>>12) | ((a7&((1<< 6)-1))<<20); /* (32-12) +  6 = 20+ 6 = 26 */
	h[9] = (a7>> 6)&((1<<25)-1); /*                                     25 */
}

static __always_inline void fe_frombytes(fe *h, const u8 *s)
{
	fe_frombytes_impl(h->v, s);
}

static __always_inline u8 /*bool*/
addcarryx_u25(u8 /*bool*/ c, u32 a, u32 b, u32 *low)
{
	/* This function extracts 25 bits of result and 1 bit of carry
	 * (26 total), so a 32-bit intermediate is sufficient.
	 */
	u32 x = a + b + c;
	*low = x & ((1 << 25) - 1);
	return (x >> 25) & 1;
}

static __always_inline u8 /*bool*/
addcarryx_u26(u8 /*bool*/ c, u32 a, u32 b, u32 *low)
{
	/* This function extracts 26 bits of result and 1 bit of carry
	 * (27 total), so a 32-bit intermediate is sufficient.
	 */
	u32 x = a + b + c;
	*low = x & ((1 << 26) - 1);
	return (x >> 26) & 1;
}

static __always_inline u8 /*bool*/
subborrow_u25(u8 /*bool*/ c, u32 a, u32 b, u32 *low)
{
	/* This function extracts 25 bits of result and 1 bit of borrow
	 * (26 total), so a 32-bit intermediate is sufficient.
	 */
	u32 x = a - b - c;
	*low = x & ((1 << 25) - 1);
	return x >> 31;
}

Annotation

Implementation Notes