Internet DRAFT - draft-josefsson-ntruprime-streamlined

draft-josefsson-ntruprime-streamlined







Internet Engineering Task Force                             S. Josefsson
Internet-Draft                                               11 May 2023
Intended status: Informational                                          
Expires: 12 November 2023


                   Streamlined NTRU Prime: sntrup761
                draft-josefsson-ntruprime-streamlined-00

Abstract

   We provide an algorithm introduction, reference code and test vectors
   for the Streamlined NTRU Prime key-encapsulation mechanism
   "sntrup761".

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 12 November 2023.

Copyright Notice

   Copyright (c) 2023 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.






Josefsson               Expires 12 November 2023                [Page 1]

Internet-Draft                  sntrup761                       May 2023


Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   2
   2.  Streamlined NTRU Prime: key generation  . . . . . . . . . . .   3
   3.  Streamlined NTRU Prime: encapsulation . . . . . . . . . . . .   3
   4.  Streamlined NTRU Prime: decapsulation . . . . . . . . . . . .   3
   5.  Streamlined NTRU Prime: Complete Sage implementation  . . . .   4
   6.  Streamlined NTRU Prime: Complete C implementation . . . . . .  13
     6.1.  sntrup761.h . . . . . . . . . . . . . . . . . . . . . . .  13
     6.2.  sntrup761.c . . . . . . . . . . . . . . . . . . . . . . .  14
     6.3.  sntrup761-test.c  . . . . . . . . . . . . . . . . . . . .  36
     6.4.  drbg-ctr.h  . . . . . . . . . . . . . . . . . . . . . . .  46
     6.5.  drbg-ctr.c  . . . . . . . . . . . . . . . . . . . . . . .  46
     6.6.  sha512.h, sha512.c, aes256_ecb.h, aes256_ecb.c  . . . . .  48
   7.  Streamlined NTRU Prime: Test Vectors  . . . . . . . . . . . .  50
   8.  Acknowledgements  . . . . . . . . . . . . . . . . . . . . . .  57
   9.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .  57
   10. Security Considerations . . . . . . . . . . . . . . . . . . .  57
   11. References  . . . . . . . . . . . . . . . . . . . . . . . . .  58
     11.1.  Normative References . . . . . . . . . . . . . . . . . .  58
     11.2.  Informative References . . . . . . . . . . . . . . . . .  58
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  58

1.  Introduction

   Streamlined NTRU Prime [NTRUPrime] [NTRUPrimePQCS] provides post-
   quantum small lattice-based key-encapsulation mechanisms.  The
   variant sntrup761 has been implemented widely.

   The focus of this document is to aid implementers that wish to
   implement Streamlined NTRU Prime sntrup761, by providing an
   introduction to the algorithm, Sage and C reference code with test
   vectors.

   The original NTRU Prime paper [NTRUPrime] and the primary submission
   document of NTRU Prime to NIST's Post-Quantum Cryptography
   Standardization Project" [NTRUPrimePQCS] provide background, and is
   the source for the majority of content in this document.

   Instead of attempting to describe the algorithm in human language, we
   refer to the exact algorithm description offered in SageMath
   [SageMath].  For traditional implementation, we also offer a
   reference C implementation and a test driver that is able to
   reproduce the test vectors.







Josefsson               Expires 12 November 2023                [Page 2]

Internet-Draft                  sntrup761                       May 2023


2.  Streamlined NTRU Prime: key generation

   The following algorithm outputs the Streamlined NTRU Prime public/
   private key-pair, and the session key.

   def KEM_KeyGen():
     pk,sk = ZKeyGen()
     sk += pk
     rho = Inputs_randomenc()
     sk += rho
     sk += Hash4(pk)
     return pk,sk

                                  Figure 1

3.  Streamlined NTRU Prime: encapsulation

   The following algorithm outputs the Streamlined NTRU Prime
   encapsulated session key.

   def Encap(pk):
     r = Inputs_random()
     C,r_enc = Hide(r,pk)
     return C,HashSession(1,r_enc,C)

                                  Figure 2

4.  Streamlined NTRU Prime: decapsulation

   The following algorithm outputs the Streamlined NTRU Prime
   decapsulated session key.




















Josefsson               Expires 12 November 2023                [Page 3]

Internet-Draft                  sntrup761                       May 2023


   def Decap(C,sk):
     Corig = C
     c_inner,C = C[:Ciphertexts_bytes],C[Ciphertexts_bytes:]
     gamma,C = C[:Confirm_bytes],C[Confirm_bytes:]
     assert len(C) == 0

     sk_inner,sk = sk[:SecretKeys_bytes],sk[SecretKeys_bytes:]
     pk,sk = sk[:PublicKeys_bytes],sk[PublicKeys_bytes:]
     rho,sk = sk[:Inputs_bytes],sk[Inputs_bytes:]
     cache = None
     cache,sk = sk[:Hash_bytes],sk[Hash_bytes:]
     assert len(sk) == 0

     r = ZDecrypt(c_inner,sk_inner)
     Cnew,r_enc = Hide(r,pk,cache)

     assert len(r_enc) == Inputs_bytes
     assert len(rho) == Inputs_bytes

     if Cnew == Corig: return HashSession(1,r_enc,Corig)
     return HashSession(0,rho,Corig)

                                  Figure 3

5.  Streamlined NTRU Prime: Complete Sage implementation

   The functions above call several other functions, which are specified
   below.

sntrup = { # p,q,w
  'sntrup761':    (761,4591,286),
  'sntrup653':    (653,4621,288),
  'sntrup857':    (857,5167,322),
  'sntrup953':    (953,6343,396),
  'sntrup1013':   (1013,7177,448),
  'sntrup1277':   (1277,7879,492),
}

def setparameters(system,random8):
  global p
  global q
  global w

  global PublicKeys_bytes
  global SecretKeys_bytes
  global Ciphertexts_bytes
  global Inputs_bytes
  global Confirm_bytes



Josefsson               Expires 12 November 2023                [Page 4]

Internet-Draft                  sntrup761                       May 2023


  global Hash_bytes
  global Rq_encode
  global Inputs_random
  global ZKeyGen
  global ZEncrypt
  global ZDecrypt

  if system in sntrup:
    p,q,w = sntrup[system]
  else:
    raise Exception('%s is not one of the selected parameter sets' % system)

  # ----- parameter requirements
  # tested later: irreducibility of x^p-x-1 mod q

  assert p.is_prime()
  assert q.is_prime()
  assert w > 0
  assert 2*p >= 3*w
  assert q >= 16*w+1
  assert q%6 == 1 # spec allows 5 but these tests do not
  assert p%4 == 1 # spec allows 3 but ref C code does not

  # ----- arithmetic mod 3

  F3 = GF(3)
  def ZZ_fromF3(c):
    assert c in F3
    return ZZ(c+1)-1

  # ----- arithmetic mod q

  Fq = GF(q)
  q12 = ZZ((q-1)/2)
  def ZZ_fromFq(c):
    assert c in Fq
    return ZZ(c+q12)-q12

  # ----- polynomials over integers

  global R

  Zx.<x> = ZZ[]
  R.<xp> = Zx.quotient(x^p-x-1)

  def Weightw_is(r):
    assert r in R
    return w == len([i for i in range(p) if r[i] != 0])



Josefsson               Expires 12 November 2023                [Page 5]

Internet-Draft                  sntrup761                       May 2023


  def Small_is(r):
    assert r in R
    return all(abs(r[i]) <= 1 for i in range(p))

  def Short_is(r):
    return Small_is(r) and Weightw_is(r)

  # ----- polynomials mod 3

  F3x.<x3> = F3[]
  R3.<x3p> = F3x.quotient(x^p-x-1)

  def R_fromR3(r):
    assert r in R3
    return R([ZZ_fromF3(r[i]) for i in range(p)])

  def R3_fromR(r):
    assert r in R
    return R3([r[i] for i in range(p)])

  # ----- polynomials mod q

  Fqx.<xq> = Fq[]
  assert (xq^p-xq-1).is_irreducible()

  global Rq
  Rq.<xqp> = Fqx.quotient(x^p-x-1)

  global R_fromRq
  def R_fromRq(r):
    assert r in Rq
    return R([ZZ_fromFq(r[i]) for i in range(p)])

  global Rq_fromR
  def Rq_fromR(r):
    assert r in R
    return Rq([r[i] for i in range(p)])

  # ----- rounded polynomials mod q

  def Rounded_is(r):
    assert r in R
    return (all(r[i]%3 == 0 for i in range(p))
      and all(r[i] >= -q12 for i in range(p))
      and all(r[i] <= q12 for i in range(p)))

  def Round(a):
    assert a in Rq



Josefsson               Expires 12 November 2023                [Page 6]

Internet-Draft                  sntrup761                       May 2023


    c = R_fromRq(a)
    r = [3*round(c[i]/3) for i in range(p)]
    assert all(abs(r[i]-c[i]) <= 1 for i in range(p))
    r = R(r)
    assert Rounded_is(r)
    return r

  # ----- sorting to generate short polynomial

  global Short_fromlist
  def Short_fromlist(L): # L is list of p uint32
    L = [L[i]&-2 for i in range(w)] + [(L[i]&-3)|1 for i in range(w,p)]
    assert all(L[i]%2 == 0 for i in range(w))
    assert all(L[i]%4 == 1 for i in range(w,p))
    L.sort()
    L = [(L[i]%4)-1 for i in range(p)]
    assert all(abs(L[i]) <= 1 for i in range(p))
    assert sum(abs(L[i]) for i in range(p)) == w
    r = R(L)
    assert Short_is(r)
    return r

  # ----- underlying hash function

  import hashlib

  global sha512
  def sha512(s):
    h = hashlib.sha512()
    h.update(s)
    return h.digest()

  Hash_bytes = 32
  def Hash(s): return sha512(s)[:Hash_bytes]

  def Hash0(s): return Hash(chr(0)+s)
  def Hash1(s): return Hash(chr(1)+s)
  def Hash2(s): return Hash(chr(2)+s)
  def Hash3(s): return Hash(chr(3)+s)
  def Hash4(s): return Hash(chr(4)+s)

  # ----- higher-level randomness

  def urandom32():
    c0 = random8()
    c1 = random8()
    c2 = random8()
    c3 = random8()



Josefsson               Expires 12 November 2023                [Page 7]

Internet-Draft                  sntrup761                       May 2023


    return c0 + 256*c1 + 65536*c2 + 16777216*c3

  global Short_random
  def Short_random(): # R element with w coeffs +-1
    L = [urandom32() for i in range(p)]
    return Short_fromlist(L)

  def randomrange3():
    return ((urandom32() & 0x3fffffff) * 3) >> 30

  def Small_random():
    r = R([randomrange3()-1 for i in range(p)])
    assert Small_is(r)
    return r

  # ----- Streamlined NTRU Prime Core

  global KeyGen
  global Encrypt
  global Decrypt

  def KeyGen():
    while True:
      g = Small_random()
      if R3_fromR(g).is_unit(): break
    f = Short_random()
    h = Rq_fromR(g)/Rq_fromR(3*f)
    return h,(f,1/R3_fromR(g))

  def Encrypt(r,h):
    assert Short_is(r)
    assert h in Rq
    return Round(h*Rq_fromR(r))

  def Decrypt(c,k):
    f,v = k
    assert Rounded_is(c)
    assert Short_is(f)
    assert v in R3
    e = R3_fromR(R_fromRq(3*Rq_fromR(f)*Rq_fromR(c)))
    r = R_fromR3(e*v)
    if Weightw_is(r): return r
    return R([1]*w+[0]*(p-w))

  # ----- strings

  global tostring
  def tostring(s):



Josefsson               Expires 12 November 2023                [Page 8]

Internet-Draft                  sntrup761                       May 2023


    return ''.join(chr(si) for si in s)

  def fromstring(s):
    return [ord(si) for si in s]

  # ----- encoding small polynomials (including short polynomials)

  Small_bytes = ceil(p/4)

  def Small_encode(r):
    assert Small_is(r)
    R = [r[i]+1 for i in range(p)]
    while len(R) < 4*Small_bytes: R += [0]
    assert all(R[i] >= 0 for i in range(4*Small_bytes))
    assert all(R[i] <= 2 for i in range(4*Small_bytes))
    assert len(R) >= p
    assert len(R)%4 == 0
    S = [R[i]+4*R[i+1]+16*R[i+2]+64*R[i+3] for i in range(0,len(R),4)]
    return tostring(S)

  def Small_decode(s):
    S = fromstring(s)
    r = [(S[i//4]//4^(i%4))%4 for i in range(p)]
    assert all(r[i] >= 0 for i in range(p))
    assert all(r[i] <= 2 for i in range(p))
    r = [r[i]-1 for i in range(p)]
    return R(r)

  # ----- infrastructure for more general encoding

  limit = 16384

  def Encode(R,M):
    if len(M) == 0: return []
    S = []
    if len(M) == 1:
      r,m = R[0],M[0]
      while m > 1:
        S += [r%256]
        r,m = r//256,(m+255)//256
      return S
    R2,M2 = [],[]
    for i in range(0,len(M)-1,2):
      m,r = M[i]*M[i+1],R[i]+M[i]*R[i+1]
      while m >= limit:
        S += [r%256]
        r,m = r//256,(m+255)//256
      R2 += [r]



Josefsson               Expires 12 November 2023                [Page 9]

Internet-Draft                  sntrup761                       May 2023


      M2 += [m]
    if len(M)&1:
      R2 += [R[-1]]
      M2 += [M[-1]]
    return S+Encode(R2,M2)

  def Decode(S,M):
    if len(M) == 0: return []
    if len(M) == 1: return [sum(S[i]*256**i for i in range(len(S)))%M[0]]
    k = 0
    bottom,M2 = [],[]
    for i in range(0,len(M)-1,2):
      m,r,t = M[i]*M[i+1],0,1
      while m >= limit:
        r,t,k,m = r+S[k]*t,t*256,k+1,(m+255)//256
      bottom += [(r,t)]
      M2 += [m]
    if len(M)&1:
      M2 += [M[-1]]
    R2 = Decode(S[k:],M2)
    R = []
    for i in range(0,len(M)-1,2):
      r,t = bottom[i//2]
      r += t*R2[i//2]
      R += [r%M[i]]
      R += [(r//M[i])%M[i+1]]
    if len(M)&1:
      R += [R2[-1]]
    return R

  # ----- encoding general polynomials

  def Rq_encode(r):
    assert r in Rq
    R = [ZZ_fromFq(r[i])+q12 for i in range(p)]
    M = [q]*p
    assert all(0 <= R[i] for i in range(p))
    assert all(R[i] < M[i] for i in range(p))
    return tostring(Encode(R,M))

  def Rq_decode(s):
    assert len(s) == Rq_bytes
    M = [q]*p
    R = Decode(fromstring(s),M)
    assert all(0 <= R[i] for i in range(p))
    assert all(R[i] < M[i] for i in range(p))
    r = [R[i]-q12 for i in range(p)]
    return Rq(r)



Josefsson               Expires 12 November 2023               [Page 10]

Internet-Draft                  sntrup761                       May 2023


  global Rq_bytes
  Rq_bytes = len(Rq_encode(Rq(0)))

  # ----- encoding rounded polynomials

  def Rounded_encode(r):
    assert Rounded_is(r)
    R = [ZZ((ZZ_fromFq(r[i])+q12)/3) for i in range(p)]
    M = [ZZ((q-1)/3+1)]*p
    assert all(0 <= R[i] for i in range(p))
    assert all(R[i] < M[i] for i in range(p))
    return tostring(Encode(R,M))

  def Rounded_decode(s):
    assert len(s) == Rounded_bytes
    M = [ZZ((q-1)/3+1)]*p
    r = Decode(fromstring(s),M)
    assert all(0 <= r[i] for i in range(p))
    assert all(r[i] < M[i] for i in range(p))
    r = [3*r[i]-q12 for i in range(p)]
    return R(r)

  global Rounded_bytes
  Rounded_bytes = len(Rounded_encode(R(0)))

  # ----- Streamlined NTRU Prime Core plus encoding

  Inputs_random = Short_random
  Inputs_encode = Small_encode
  Inputs_bytes = Small_bytes

  Ciphertexts_bytes = Rounded_bytes
  SecretKeys_bytes = 2*Small_bytes
  PublicKeys_bytes = Rq_bytes

  def Inputs_randomenc():
    rho = [random8() for i in range(Small_bytes)]
    return tostring(rho)

  def ZKeyGen():
    h,(f,v) = KeyGen()
    return Rq_encode(h),Small_encode(f)+Small_encode(R_fromR3(v))

  def ZEncrypt(r,pk):
    assert len(pk) == PublicKeys_bytes
    h = Rq_decode(pk)
    return Rounded_encode(Encrypt(r,h))




Josefsson               Expires 12 November 2023               [Page 11]

Internet-Draft                  sntrup761                       May 2023


  def ZDecrypt(c,sk):
    assert len(sk) == SecretKeys_bytes
    assert len(c) == Ciphertexts_bytes
    f = Small_decode(sk[:Small_bytes])
    v = R3_fromR(Small_decode(sk[Small_bytes:]))
    c = Rounded_decode(c)
    return Decrypt(c,(f,v))

  # ----- confirmation hash

  Confirm_bytes = 32

  def HashConfirm(r,K,cache=None):
    assert len(r) == Inputs_bytes
    assert len(K) == PublicKeys_bytes
    if not cache: cache = Hash4(K)
    assert cache == Hash4(K)
    r = Hash3(r)
    return Hash2(r+cache)

  # ----- session-key hash

  global HashSession
  def HashSession(b,y,z):
    assert len(y) == Inputs_bytes
    assert len(z) == Ciphertexts_bytes+Confirm_bytes
    assert b in [0,1]
    y = Hash3(y)
    if b == 1: return Hash1(y+z)
    return Hash0(y+z)

  # ----- Streamlined NTRU Prime

  # KeyGen' in Streamlined NTRU Prime spec
  global KEM_KeyGen
  def KEM_KeyGen():
    pk,sk = ZKeyGen()
    sk += pk
    rho = Inputs_randomenc()
    sk += rho
    sk += Hash4(pk)
    return pk,sk

  global Hide
  def Hide(r,pk,cache=None):
    r_enc = Inputs_encode(r)
    c = ZEncrypt(r,pk)
    gamma = HashConfirm(r_enc,pk,cache)



Josefsson               Expires 12 November 2023               [Page 12]

Internet-Draft                  sntrup761                       May 2023


    c = c+gamma
    return c,r_enc

  global Encap
  def Encap(pk):
    r = Inputs_random()
    C,r_enc = Hide(r,pk)
    return C,HashSession(1,r_enc,C)

  global Decap
  def Decap(C,sk):
    Corig = C
    c_inner,C = C[:Ciphertexts_bytes],C[Ciphertexts_bytes:]
    gamma,C = C[:Confirm_bytes],C[Confirm_bytes:]
    assert len(C) == 0

    sk_inner,sk = sk[:SecretKeys_bytes],sk[SecretKeys_bytes:]
    pk,sk = sk[:PublicKeys_bytes],sk[PublicKeys_bytes:]
    rho,sk = sk[:Inputs_bytes],sk[Inputs_bytes:]
    cache = None
    cache,sk = sk[:Hash_bytes],sk[Hash_bytes:]
    assert len(sk) == 0

    r = ZDecrypt(c_inner,sk_inner)
    Cnew,r_enc = Hide(r,pk,cache)

    assert len(r_enc) == Inputs_bytes
    assert len(rho) == Inputs_bytes

    if Cnew == Corig: return HashSession(1,r_enc,Corig)
    return HashSession(0,rho,Corig)

                               Figure 4

6.  Streamlined NTRU Prime: Complete C implementation

6.1.  sntrup761.h














Josefsson               Expires 12 November 2023               [Page 13]

Internet-Draft                  sntrup761                       May 2023


/*
 * Derived from public domain source, written by (in alphabetical order):
 * - Daniel J. Bernstein
 * - Chitchanok Chuengsatiansup
 * - Tanja Lange
 * - Christine van Vredendaal
 */

#ifndef SNTRUP761_H
#define SNTRUP761_H

#include <string.h>
#include <stdint.h>

#define SNTRUP761_SECRETKEY_SIZE 1763
#define SNTRUP761_PUBLICKEY_SIZE 1158
#define SNTRUP761_CIPHERTEXT_SIZE 1039
#define SNTRUP761_SIZE 32

typedef void sntrup761_random_func (void *ctx, size_t length, uint8_t *dst);

void
sntrup761_keypair (uint8_t *pk, uint8_t *sk,
                   void *random_ctx, sntrup761_random_func *random);

void
sntrup761_enc (uint8_t *c, uint8_t *k, const uint8_t *pk,
               void *random_ctx, sntrup761_random_func *random);

void
sntrup761_dec (uint8_t *k, const uint8_t *c, const uint8_t *sk);

#endif /* SNTRUP761_H */

                               Figure 5

6.2.  sntrup761.c

/*
 * Derived from public domain source, written by (in alphabetical order):
 * - Daniel J. Bernstein
 * - Chitchanok Chuengsatiansup
 * - Tanja Lange
 * - Christine van Vredendaal
 */

#include "sntrup761.h"




Josefsson               Expires 12 November 2023               [Page 14]

Internet-Draft                  sntrup761                       May 2023


#include "sha512.h"

/* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */
#define int32_MINMAX(a,b) \
do { \
  int64_t ab = (int64_t)b ^ (int64_t)a; \
  int64_t c = (int64_t)b - (int64_t)a; \
  c ^= ab & (c ^ b); \
  c >>= 31; \
  c &= ab; \
  a ^= c; \
  b ^= c; \
} while(0)

/* from supercop-20201130/crypto_sort/int32/portable4/sort.c */
static void
crypto_sort_int32 (void *array, long long n)
{
  long long top, p, q, r, i, j;
  int32_t *x = array;

  if (n < 2)
    return;
  top = 1;
  while (top < n - top)
    top += top;

  for (p = top; p >= 1; p >>= 1)
    {
      i = 0;
      while (i + 2 * p <= n)
        {
          for (j = i; j < i + p; ++j)
            int32_MINMAX (x[j], x[j + p]);
          i += 2 * p;
        }
      for (j = i; j < n - p; ++j)
        int32_MINMAX (x[j], x[j + p]);

      i = 0;
      j = 0;
      for (q = top; q > p; q >>= 1)
        {
          if (j != i)
            for (;;)
              {
                if (j == n - q)
                  goto done;



Josefsson               Expires 12 November 2023               [Page 15]

Internet-Draft                  sntrup761                       May 2023


                int32_t a = x[j + p];
                for (r = q; r > p; r >>= 1)
                  int32_MINMAX (a, x[j + r]);
                x[j + p] = a;
                ++j;
                if (j == i + p)
                  {
                    i += 2 * p;
                    break;
                  }
              }
          while (i + p <= n - q)
            {
              for (j = i; j < i + p; ++j)
                {
                  int32_t a = x[j + p];
                  for (r = q; r > p; r >>= 1)
                    int32_MINMAX (a, x[j + r]);
                  x[j + p] = a;
                }
              i += 2 * p;
            }
          /* now i + p > n - q */
          j = i;
          while (j < n - q)
            {
              int32_t a = x[j + p];
              for (r = q; r > p; r >>= 1)
                int32_MINMAX (a, x[j + r]);
              x[j + p] = a;
              ++j;
            }

        done:;
        }
    }
}

/* from supercop-20201130/crypto_sort/uint32/useint32/sort.c */

/* can save time by vectorizing xor loops */
/* can save time by integrating xor loops with int32_sort */

static void
crypto_sort_uint32 (void *array, long long n)
{
  uint32_t *x = array;
  long long j;



Josefsson               Expires 12 November 2023               [Page 16]

Internet-Draft                  sntrup761                       May 2023


  for (j = 0; j < n; ++j)
    x[j] ^= 0x80000000;
  crypto_sort_int32 (array, n);
  for (j = 0; j < n; ++j)
    x[j] ^= 0x80000000;
}

/* from supercop-20201130/crypto_kem/sntrup761/ref/uint32.c */

/*
CPU division instruction typically takes time depending on x.
This software is designed to take time independent of x.
Time still varies depending on m; user must ensure that m is constant.
Time also varies on CPUs where multiplication is variable-time.
There could be more CPU issues.
There could also be compiler issues.
*/

static void
uint32_divmod_uint14 (uint32_t * q, uint16_t * r, uint32_t x, uint16_t m)
{
  uint32_t v = 0x80000000;
  uint32_t qpart;
  uint32_t mask;

  v /= m;

  /* caller guarantees m > 0 */
  /* caller guarantees m < 16384 */
  /* vm <= 2^31 <= vm+m-1 */
  /* xvm <= 2^31 x <= xvm+x(m-1) */

  *q = 0;

  qpart = (x * (uint64_t) v) >> 31;
  /* 2^31 qpart <= xv <= 2^31 qpart + 2^31-1 */
  /* 2^31 qpart m <= xvm <= 2^31 qpart m + (2^31-1)m */
  /* 2^31 qpart m <= 2^31 x <= 2^31 qpart m + (2^31-1)m + x(m-1) */
  /* 0 <= 2^31 newx <= (2^31-1)m + x(m-1) */
  /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */
  /* 0 <= newx <= (1-1/2^31)(2^14-1) + (2^32-1)((2^14-1)-1)/2^31 */

  x -= qpart * m;
  *q += qpart;
  /* x <= 49146 */

  qpart = (x * (uint64_t) v) >> 31;
  /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */



Josefsson               Expires 12 November 2023               [Page 17]

Internet-Draft                  sntrup761                       May 2023


  /* 0 <= newx <= m + 49146(2^14-1)/2^31 */
  /* 0 <= newx <= m + 0.4 */
  /* 0 <= newx <= m */

  x -= qpart * m;
  *q += qpart;
  /* x <= m */

  x -= m;
  *q += 1;
  mask = -(x >> 31);
  x += mask & (uint32_t) m;
  *q += mask;
  /* x < m */

  *r = x;
}


static uint16_t
uint32_mod_uint14 (uint32_t x, uint16_t m)
{
  uint32_t q;
  uint16_t r;
  uint32_divmod_uint14 (&q, &r, x, m);
  return r;
}

/* from supercop-20201130/crypto_kem/sntrup761/ref/int32.c */

static void
int32_divmod_uint14 (int32_t * q, uint16_t * r, int32_t x, uint16_t m)
{
  uint32_t uq, uq2;
  uint16_t ur, ur2;
  uint32_t mask;

  uint32_divmod_uint14 (&uq, &ur, 0x80000000 + (uint32_t) x, m);
  uint32_divmod_uint14 (&uq2, &ur2, 0x80000000, m);
  ur -= ur2;
  uq -= uq2;
  mask = -(uint32_t) (ur >> 15);
  ur += mask & m;
  uq += mask;
  *r = ur;
  *q = uq;
}




Josefsson               Expires 12 November 2023               [Page 18]

Internet-Draft                  sntrup761                       May 2023


static uint16_t
int32_mod_uint14 (int32_t x, uint16_t m)
{
  int32_t q;
  uint16_t r;
  int32_divmod_uint14 (&q, &r, x, m);
  return r;
}

/* from supercop-20201130/crypto_kem/sntrup761/ref/paramsmenu.h */
#define p 761
#define q 4591
#define Rounded_bytes 1007
#define Rq_bytes 1158
#define w 286

/* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.h */

/* Decode(R,s,M,len) */
/* assumes 0 < M[i] < 16384 */
/* produces 0 <= R[i] < M[i] */

/* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.c */

static void
Decode (uint16_t * out, const unsigned char *S, const uint16_t * M,
        long long len)
{
  if (len == 1)
    {
      if (M[0] == 1)
        *out = 0;
      else if (M[0] <= 256)
        *out = uint32_mod_uint14 (S[0], M[0]);
      else
        *out = uint32_mod_uint14 (S[0] + (((uint16_t) S[1]) << 8), M[0]);
    }
  if (len > 1)
    {
      uint16_t R2[(len + 1) / 2];
      uint16_t M2[(len + 1) / 2];
      uint16_t bottomr[len / 2];
      uint32_t bottomt[len / 2];
      long long i;
      for (i = 0; i < len - 1; i += 2)
        {
          uint32_t m = M[i] * (uint32_t) M[i + 1];
          if (m > 256 * 16383)



Josefsson               Expires 12 November 2023               [Page 19]

Internet-Draft                  sntrup761                       May 2023


            {
              bottomt[i / 2] = 256 * 256;
              bottomr[i / 2] = S[0] + 256 * S[1];
              S += 2;
              M2[i / 2] = (((m + 255) >> 8) + 255) >> 8;
            }
          else if (m >= 16384)
            {
              bottomt[i / 2] = 256;
              bottomr[i / 2] = S[0];
              S += 1;
              M2[i / 2] = (m + 255) >> 8;
            }
          else
            {
              bottomt[i / 2] = 1;
              bottomr[i / 2] = 0;
              M2[i / 2] = m;
            }
        }
      if (i < len)
        M2[i / 2] = M[i];
      Decode (R2, S, M2, (len + 1) / 2);
      for (i = 0; i < len - 1; i += 2)
        {
          uint32_t r = bottomr[i / 2];
          uint32_t r1;
          uint16_t r0;
          r += bottomt[i / 2] * R2[i / 2];
          uint32_divmod_uint14 (&r1, &r0, r, M[i]);
          r1 = uint32_mod_uint14 (r1, M[i + 1]);        /* only needed for invalid inputs */
          *out++ = r0;
          *out++ = r1;
        }
      if (i < len)
        *out++ = R2[i / 2];
    }
}

/* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.h */

/* Encode(s,R,M,len) */
/* assumes 0 <= R[i] < M[i] < 16384 */

/* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.c */

/* 0 <= R[i] < M[i] < 16384 */
static void



Josefsson               Expires 12 November 2023               [Page 20]

Internet-Draft                  sntrup761                       May 2023


Encode (unsigned char *out, const uint16_t * R, const uint16_t * M,
        long long len)
{
  if (len == 1)
    {
      uint16_t r = R[0];
      uint16_t m = M[0];
      while (m > 1)
        {
          *out++ = r;
          r >>= 8;
          m = (m + 255) >> 8;
        }
    }
  if (len > 1)
    {
      uint16_t R2[(len + 1) / 2];
      uint16_t M2[(len + 1) / 2];
      long long i;
      for (i = 0; i < len - 1; i += 2)
        {
          uint32_t m0 = M[i];
          uint32_t r = R[i] + R[i + 1] * m0;
          uint32_t m = M[i + 1] * m0;
          while (m >= 16384)
            {
              *out++ = r;
              r >>= 8;
              m = (m + 255) >> 8;
            }
          R2[i / 2] = r;
          M2[i / 2] = m;
        }
      if (i < len)
        {
          R2[i / 2] = R[i];
          M2[i / 2] = M[i];
        }
      Encode (out, R2, M2, (len + 1) / 2);
    }
}

/* from supercop-20201130/crypto_kem/sntrup761/ref/kem.c */

/* ----- masks */

/* return -1 if x!=0; else return 0 */
static int



Josefsson               Expires 12 November 2023               [Page 21]

Internet-Draft                  sntrup761                       May 2023


int16_t_nonzero_mask (int16_t x)
{
  uint16_t u = x;               /* 0, else 1...65535 */
  uint32_t v = u;               /* 0, else 1...65535 */
  v = -v;                       /* 0, else 2^32-65535...2^32-1 */
  v >>= 31;                     /* 0, else 1 */
  return -v;                    /* 0, else -1 */
}

/* return -1 if x<0; otherwise return 0 */
static int
int16_t_negative_mask (int16_t x)
{
  uint16_t u = x;
  u >>= 15;
  return -(int) u;
  /* alternative with gcc -fwrapv: */
  /* x>>15 compiles to CPU's arithmetic right shift */
}

/* ----- arithmetic mod 3 */

typedef int8_t small;

/* F3 is always represented as -1,0,1 */
/* so ZZ_fromF3 is a no-op */

/* x must not be close to top int16_t */
static small
F3_freeze (int16_t x)
{
  return int32_mod_uint14 (x + 1, 3) - 1;
}

/* ----- arithmetic mod q */

#define q12 ((q-1)/2)
typedef int16_t Fq;
/* always represented as -q12...q12 */
/* so ZZ_fromFq is a no-op */

/* x must not be close to top int32 */
static Fq
Fq_freeze (int32_t x)
{
  return int32_mod_uint14 (x + q12, q) - q12;
}




Josefsson               Expires 12 November 2023               [Page 22]

Internet-Draft                  sntrup761                       May 2023


static Fq
Fq_recip (Fq a1)
{
  int i = 1;
  Fq ai = a1;

  while (i < q - 2)
    {
      ai = Fq_freeze (a1 * (int32_t) ai);
      i += 1;
    }
  return ai;
}

/* ----- small polynomials */

/* 0 if Weightw_is(r), else -1 */
static int
Weightw_mask (small * r)
{
  int weight = 0;
  int i;

  for (i = 0; i < p; ++i)
    weight += r[i] & 1;
  return int16_t_nonzero_mask (weight - w);
}

/* R3_fromR(R_fromRq(r)) */
static void
R3_fromRq (small * out, const Fq * r)
{
  int i;
  for (i = 0; i < p; ++i)
    out[i] = F3_freeze (r[i]);
}

/* h = f*g in the ring R3 */
static void
R3_mult (small * h, const small * f, const small * g)
{
  small fg[p + p - 1];
  small result;
  int i, j;

  for (i = 0; i < p; ++i)
    {
      result = 0;



Josefsson               Expires 12 November 2023               [Page 23]

Internet-Draft                  sntrup761                       May 2023


      for (j = 0; j <= i; ++j)
        result = F3_freeze (result + f[j] * g[i - j]);
      fg[i] = result;
    }
  for (i = p; i < p + p - 1; ++i)
    {
      result = 0;
      for (j = i - p + 1; j < p; ++j)
        result = F3_freeze (result + f[j] * g[i - j]);
      fg[i] = result;
    }

  for (i = p + p - 2; i >= p; --i)
    {
      fg[i - p] = F3_freeze (fg[i - p] + fg[i]);
      fg[i - p + 1] = F3_freeze (fg[i - p + 1] + fg[i]);
    }

  for (i = 0; i < p; ++i)
    h[i] = fg[i];
}

/* returns 0 if recip succeeded; else -1 */
static int
R3_recip (small * out, const small * in)
{
  small f[p + 1], g[p + 1], v[p + 1], r[p + 1];
  int i, loop, delta;
  int sign, swap, t;

  for (i = 0; i < p + 1; ++i)
    v[i] = 0;
  for (i = 0; i < p + 1; ++i)
    r[i] = 0;
  r[0] = 1;
  for (i = 0; i < p; ++i)
    f[i] = 0;
  f[0] = 1;
  f[p - 1] = f[p] = -1;
  for (i = 0; i < p; ++i)
    g[p - 1 - i] = in[i];
  g[p] = 0;

  delta = 1;

  for (loop = 0; loop < 2 * p - 1; ++loop)
    {
      for (i = p; i > 0; --i)



Josefsson               Expires 12 November 2023               [Page 24]

Internet-Draft                  sntrup761                       May 2023


        v[i] = v[i - 1];
      v[0] = 0;

      sign = -g[0] * f[0];
      swap = int16_t_negative_mask (-delta) & int16_t_nonzero_mask (g[0]);
      delta ^= swap & (delta ^ -delta);
      delta += 1;

      for (i = 0; i < p + 1; ++i)
        {
          t = swap & (f[i] ^ g[i]);
          f[i] ^= t;
          g[i] ^= t;
          t = swap & (v[i] ^ r[i]);
          v[i] ^= t;
          r[i] ^= t;
        }

      for (i = 0; i < p + 1; ++i)
        g[i] = F3_freeze (g[i] + sign * f[i]);
      for (i = 0; i < p + 1; ++i)
        r[i] = F3_freeze (r[i] + sign * v[i]);

      for (i = 0; i < p; ++i)
        g[i] = g[i + 1];
      g[p] = 0;
    }

  sign = f[0];
  for (i = 0; i < p; ++i)
    out[i] = sign * v[p - 1 - i];

  return int16_t_nonzero_mask (delta);
}

/* ----- polynomials mod q */

/* h = f*g in the ring Rq */
static void
Rq_mult_small (Fq * h, const Fq * f, const small * g)
{
  Fq fg[p + p - 1];
  Fq result;
  int i, j;

  for (i = 0; i < p; ++i)
    {
      result = 0;



Josefsson               Expires 12 November 2023               [Page 25]

Internet-Draft                  sntrup761                       May 2023


      for (j = 0; j <= i; ++j)
        result = Fq_freeze (result + f[j] * (int32_t) g[i - j]);
      fg[i] = result;
    }
  for (i = p; i < p + p - 1; ++i)
    {
      result = 0;
      for (j = i - p + 1; j < p; ++j)
        result = Fq_freeze (result + f[j] * (int32_t) g[i - j]);
      fg[i] = result;
    }

  for (i = p + p - 2; i >= p; --i)
    {
      fg[i - p] = Fq_freeze (fg[i - p] + fg[i]);
      fg[i - p + 1] = Fq_freeze (fg[i - p + 1] + fg[i]);
    }

  for (i = 0; i < p; ++i)
    h[i] = fg[i];
}

/* h = 3f in Rq */
static void
Rq_mult3 (Fq * h, const Fq * f)
{
  int i;

  for (i = 0; i < p; ++i)
    h[i] = Fq_freeze (3 * f[i]);
}

/* out = 1/(3*in) in Rq */
/* returns 0 if recip succeeded; else -1 */
static int
Rq_recip3 (Fq * out, const small * in)
{
  Fq f[p + 1], g[p + 1], v[p + 1], r[p + 1];
  int i, loop, delta;
  int swap, t;
  int32_t f0, g0;
  Fq scale;

  for (i = 0; i < p + 1; ++i)
    v[i] = 0;
  for (i = 0; i < p + 1; ++i)
    r[i] = 0;
  r[0] = Fq_recip (3);



Josefsson               Expires 12 November 2023               [Page 26]

Internet-Draft                  sntrup761                       May 2023


  for (i = 0; i < p; ++i)
    f[i] = 0;
  f[0] = 1;
  f[p - 1] = f[p] = -1;
  for (i = 0; i < p; ++i)
    g[p - 1 - i] = in[i];
  g[p] = 0;

  delta = 1;

  for (loop = 0; loop < 2 * p - 1; ++loop)
    {
      for (i = p; i > 0; --i)
        v[i] = v[i - 1];
      v[0] = 0;

      swap = int16_t_negative_mask (-delta) & int16_t_nonzero_mask (g[0]);
      delta ^= swap & (delta ^ -delta);
      delta += 1;

      for (i = 0; i < p + 1; ++i)
        {
          t = swap & (f[i] ^ g[i]);
          f[i] ^= t;
          g[i] ^= t;
          t = swap & (v[i] ^ r[i]);
          v[i] ^= t;
          r[i] ^= t;
        }

      f0 = f[0];
      g0 = g[0];
      for (i = 0; i < p + 1; ++i)
        g[i] = Fq_freeze (f0 * g[i] - g0 * f[i]);
      for (i = 0; i < p + 1; ++i)
        r[i] = Fq_freeze (f0 * r[i] - g0 * v[i]);

      for (i = 0; i < p; ++i)
        g[i] = g[i + 1];
      g[p] = 0;
    }

  scale = Fq_recip (f[0]);
  for (i = 0; i < p; ++i)
    out[i] = Fq_freeze (scale * (int32_t) v[p - 1 - i]);

  return int16_t_nonzero_mask (delta);
}



Josefsson               Expires 12 November 2023               [Page 27]

Internet-Draft                  sntrup761                       May 2023


/* ----- rounded polynomials mod q */

static void
Round (Fq * out, const Fq * a)
{
  int i;
  for (i = 0; i < p; ++i)
    out[i] = a[i] - F3_freeze (a[i]);
}

/* ----- sorting to generate short polynomial */

static void
Short_fromlist (small * out, const uint32_t * in)
{
  uint32_t L[p];
  int i;

  for (i = 0; i < w; ++i)
    L[i] = in[i] & (uint32_t) - 2;
  for (i = w; i < p; ++i)
    L[i] = (in[i] & (uint32_t) - 3) | 1;
  crypto_sort_uint32 (L, p);
  for (i = 0; i < p; ++i)
    out[i] = (L[i] & 3) - 1;
}

/* ----- underlying hash function */

#define Hash_bytes 32

/* e.g., b = 0 means out = Hash0(in) */
static void
Hash_prefix (unsigned char *out, int b, const unsigned char *in, int inlen)
{
  unsigned char x[inlen + 1];
  unsigned char h[64];
  int i;

  x[0] = b;
  for (i = 0; i < inlen; ++i)
    x[i + 1] = in[i];
  crypto_hash_sha512 (h, x, inlen + 1);
  for (i = 0; i < 32; ++i)
    out[i] = h[i];
}

/* ----- higher-level randomness */



Josefsson               Expires 12 November 2023               [Page 28]

Internet-Draft                  sntrup761                       May 2023


static uint32_t
urandom32 (void *random_ctx, sntrup761_random_func * random)
{
  unsigned char c[4];
  uint32_t out[4];

  random (random_ctx, 4, c);
  out[0] = (uint32_t) c[0];
  out[1] = ((uint32_t) c[1]) << 8;
  out[2] = ((uint32_t) c[2]) << 16;
  out[3] = ((uint32_t) c[3]) << 24;
  return out[0] + out[1] + out[2] + out[3];
}

static void
Short_random (small * out, void *random_ctx, sntrup761_random_func * random)
{
  uint32_t L[p];
  int i;

  for (i = 0; i < p; ++i)
    L[i] = urandom32 (random_ctx, random);
  Short_fromlist (out, L);
}

static void
Small_random (small * out, void *random_ctx, sntrup761_random_func * random)
{
  int i;

  for (i = 0; i < p; ++i)
    out[i] = (((urandom32 (random_ctx, random) & 0x3fffffff) * 3) >> 30) - 1;
}

/* ----- Streamlined NTRU Prime Core */

/* h,(f,ginv) = KeyGen() */
static void
KeyGen (Fq * h, small * f, small * ginv, void *random_ctx,
        sntrup761_random_func * random)
{
  small g[p];
  Fq finv[p];

  for (;;)
    {
      Small_random (g, random_ctx, random);
      if (R3_recip (ginv, g) == 0)



Josefsson               Expires 12 November 2023               [Page 29]

Internet-Draft                  sntrup761                       May 2023


        break;
    }
  Short_random (f, random_ctx, random);
  Rq_recip3 (finv, f);          /* always works */
  Rq_mult_small (h, finv, g);
}

/* c = Encrypt(r,h) */
static void
Encrypt (Fq * c, const small * r, const Fq * h)
{
  Fq hr[p];

  Rq_mult_small (hr, h, r);
  Round (c, hr);
}

/* r = Decrypt(c,(f,ginv)) */
static void
Decrypt (small * r, const Fq * c, const small * f, const small * ginv)
{
  Fq cf[p];
  Fq cf3[p];
  small e[p];
  small ev[p];
  int mask;
  int i;

  Rq_mult_small (cf, c, f);
  Rq_mult3 (cf3, cf);
  R3_fromRq (e, cf3);
  R3_mult (ev, e, ginv);

  mask = Weightw_mask (ev);     /* 0 if weight w, else -1 */
  for (i = 0; i < w; ++i)
    r[i] = ((ev[i] ^ 1) & ~mask) ^ 1;
  for (i = w; i < p; ++i)
    r[i] = ev[i] & ~mask;
}

/* ----- encoding small polynomials (including short polynomials) */

#define Small_bytes ((p+3)/4)

/* these are the only functions that rely on p mod 4 = 1 */

static void
Small_encode (unsigned char *s, const small * f)



Josefsson               Expires 12 November 2023               [Page 30]

Internet-Draft                  sntrup761                       May 2023


{
  small x;
  int i;

  for (i = 0; i < p / 4; ++i)
    {
      x = *f++ + 1;
      x += (*f++ + 1) << 2;
      x += (*f++ + 1) << 4;
      x += (*f++ + 1) << 6;
      *s++ = x;
    }
  x = *f++ + 1;
  *s++ = x;
}

static void
Small_decode (small * f, const unsigned char *s)
{
  unsigned char x;
  int i;

  for (i = 0; i < p / 4; ++i)
    {
      x = *s++;
      *f++ = ((small) (x & 3)) - 1;
      x >>= 2;
      *f++ = ((small) (x & 3)) - 1;
      x >>= 2;
      *f++ = ((small) (x & 3)) - 1;
      x >>= 2;
      *f++ = ((small) (x & 3)) - 1;
    }
  x = *s++;
  *f++ = ((small) (x & 3)) - 1;
}

/* ----- encoding general polynomials */

static void
Rq_encode (unsigned char *s, const Fq * r)
{
  uint16_t R[p], M[p];
  int i;

  for (i = 0; i < p; ++i)
    R[i] = r[i] + q12;
  for (i = 0; i < p; ++i)



Josefsson               Expires 12 November 2023               [Page 31]

Internet-Draft                  sntrup761                       May 2023


    M[i] = q;
  Encode (s, R, M, p);
}

static void
Rq_decode (Fq * r, const unsigned char *s)
{
  uint16_t R[p], M[p];
  int i;

  for (i = 0; i < p; ++i)
    M[i] = q;
  Decode (R, s, M, p);
  for (i = 0; i < p; ++i)
    r[i] = ((Fq) R[i]) - q12;
}

/* ----- encoding rounded polynomials */

static void
Rounded_encode (unsigned char *s, const Fq * r)
{
  uint16_t R[p], M[p];
  int i;

  for (i = 0; i < p; ++i)
    R[i] = ((r[i] + q12) * 10923) >> 15;
  for (i = 0; i < p; ++i)
    M[i] = (q + 2) / 3;
  Encode (s, R, M, p);
}

static void
Rounded_decode (Fq * r, const unsigned char *s)
{
  uint16_t R[p], M[p];
  int i;

  for (i = 0; i < p; ++i)
    M[i] = (q + 2) / 3;
  Decode (R, s, M, p);
  for (i = 0; i < p; ++i)
    r[i] = R[i] * 3 - q12;
}

/* ----- Streamlined NTRU Prime Core plus encoding */

typedef small Inputs[p];        /* passed by reference */



Josefsson               Expires 12 November 2023               [Page 32]

Internet-Draft                  sntrup761                       May 2023


#define Inputs_random Short_random
#define Inputs_encode Small_encode
#define Inputs_bytes Small_bytes

#define Ciphertexts_bytes Rounded_bytes
#define SecretKeys_bytes (2*Small_bytes)
#define PublicKeys_bytes Rq_bytes

/* pk,sk = ZKeyGen() */
static void
ZKeyGen (unsigned char *pk, unsigned char *sk, void *random_ctx,
         sntrup761_random_func * random)
{
  Fq h[p];
  small f[p], v[p];

  KeyGen (h, f, v, random_ctx, random);
  Rq_encode (pk, h);
  Small_encode (sk, f);
  sk += Small_bytes;
  Small_encode (sk, v);
}

/* C = ZEncrypt(r,pk) */
static void
ZEncrypt (unsigned char *C, const Inputs r, const unsigned char *pk)
{
  Fq h[p];
  Fq c[p];
  Rq_decode (h, pk);
  Encrypt (c, r, h);
  Rounded_encode (C, c);
}

/* r = ZDecrypt(C,sk) */
static void
ZDecrypt (Inputs r, const unsigned char *C, const unsigned char *sk)
{
  small f[p], v[p];
  Fq c[p];

  Small_decode (f, sk);
  sk += Small_bytes;
  Small_decode (v, sk);
  Rounded_decode (c, C);
  Decrypt (r, c, f, v);
}




Josefsson               Expires 12 November 2023               [Page 33]

Internet-Draft                  sntrup761                       May 2023


/* ----- confirmation hash */

#define Confirm_bytes 32

/* h = HashConfirm(r,pk,cache); cache is Hash4(pk) */
static void
HashConfirm (unsigned char *h, const unsigned char *r,
             /* const unsigned char *pk, */ const unsigned char *cache)
{
  unsigned char x[Hash_bytes * 2];
  int i;

  Hash_prefix (x, 3, r, Inputs_bytes);
  for (i = 0; i < Hash_bytes; ++i)
    x[Hash_bytes + i] = cache[i];
  Hash_prefix (h, 2, x, sizeof x);
}

/* ----- session-key hash */

/* k = HashSession(b,y,z) */
static void
HashSession (unsigned char *k, int b, const unsigned char *y,
             const unsigned char *z)
{
  unsigned char x[Hash_bytes + Ciphertexts_bytes + Confirm_bytes];
  int i;

  Hash_prefix (x, 3, y, Inputs_bytes);
  for (i = 0; i < Ciphertexts_bytes + Confirm_bytes; ++i)
    x[Hash_bytes + i] = z[i];
  Hash_prefix (k, b, x, sizeof x);
}

/* ----- Streamlined NTRU Prime */

/* pk,sk = KEM_KeyGen() */
void
sntrup761_keypair (unsigned char *pk, unsigned char *sk, void *random_ctx,
                   sntrup761_random_func * random)
{
  int i;

  ZKeyGen (pk, sk, random_ctx, random);
  sk += SecretKeys_bytes;
  for (i = 0; i < PublicKeys_bytes; ++i)
    *sk++ = pk[i];
  random (random_ctx, Inputs_bytes, sk);



Josefsson               Expires 12 November 2023               [Page 34]

Internet-Draft                  sntrup761                       May 2023


  sk += Inputs_bytes;
  Hash_prefix (sk, 4, pk, PublicKeys_bytes);
}

/* c,r_enc = Hide(r,pk,cache); cache is Hash4(pk) */
static void
Hide (unsigned char *c, unsigned char *r_enc, const Inputs r,
      const unsigned char *pk, const unsigned char *cache)
{
  Inputs_encode (r_enc, r);
  ZEncrypt (c, r, pk);
  c += Ciphertexts_bytes;
  HashConfirm (c, r_enc, cache);
}

/* c,k = Encap(pk) */
void
sntrup761_enc (unsigned char *c, unsigned char *k, const unsigned char *pk,
               void *random_ctx, sntrup761_random_func * random)
{
  Inputs r;
  unsigned char r_enc[Inputs_bytes];
  unsigned char cache[Hash_bytes];

  Hash_prefix (cache, 4, pk, PublicKeys_bytes);
  Inputs_random (r, random_ctx, random);
  Hide (c, r_enc, r, pk, cache);
  HashSession (k, 1, r_enc, c);
}

/* 0 if matching ciphertext+confirm, else -1 */
static int
Ciphertexts_diff_mask (const unsigned char *c, const unsigned char *c2)
{
  uint16_t differentbits = 0;
  int len = Ciphertexts_bytes + Confirm_bytes;

  while (len-- > 0)
    differentbits |= (*c++) ^ (*c2++);
  return (1 & ((differentbits - 1) >> 8)) - 1;
}

/* k = Decap(c,sk) */
void
sntrup761_dec (unsigned char *k, const unsigned char *c, const unsigned char *sk)
{
  const unsigned char *pk = sk + SecretKeys_bytes;
  const unsigned char *rho = pk + PublicKeys_bytes;



Josefsson               Expires 12 November 2023               [Page 35]

Internet-Draft                  sntrup761                       May 2023


  const unsigned char *cache = rho + Inputs_bytes;
  Inputs r;
  unsigned char r_enc[Inputs_bytes];
  unsigned char cnew[Ciphertexts_bytes + Confirm_bytes];
  int mask;
  int i;

  ZDecrypt (r, c, sk);
  Hide (cnew, r_enc, r, pk, cache);
  mask = Ciphertexts_diff_mask (c, cnew);
  for (i = 0; i < Inputs_bytes; ++i)
    r_enc[i] ^= mask & (r_enc[i] ^ rho[i]);
  HashSession (k, 1 + mask, r_enc, c);
}

                               Figure 6

6.3.  sntrup761-test.c

   This is a test driver to compare test vectors of sntrup761.  It can
   be used to verify correctness of the sntrup761.c implementation.

#include <stdio.h>
#include <stdlib.h>

#include "sntrup761.h"

#include "drbg-ctr.h"

static void
print_hex (size_t n, const uint8_t *d)
{
  size_t i;
  for (i = 0; i < n; i++)
    printf ("%02x", d[i]);
  printf ("\n");
}

static void
test_sntrup (struct drbg_ctr_aes256_ctx *rngctx,
             sntrup761_random_func * rngfun,
             const uint8_t * xpk, const uint8_t * xsk,
             const uint8_t * xct, const uint8_t * xk)
{
  uint8_t pk[SNTRUP761_PUBLICKEY_SIZE];
  uint8_t sk[SNTRUP761_SECRETKEY_SIZE];
  uint8_t ct[SNTRUP761_CIPHERTEXT_SIZE];
  uint8_t k1[SNTRUP761_SIZE];



Josefsson               Expires 12 November 2023               [Page 36]

Internet-Draft                  sntrup761                       May 2023


  uint8_t k2[SNTRUP761_SIZE];

  sntrup761_keypair (pk, sk, rngctx, rngfun);

  if (memcmp (pk, xpk, SNTRUP761_PUBLICKEY_SIZE)
      || memcmp (sk, xsk, SNTRUP761_SECRETKEY_SIZE))
    {
      printf ("\nnstrup761_keypair:\npk = ");
      print_hex (sizeof pk, pk);
      printf ("\nsk = ");
      print_hex (sizeof sk, sk);
      abort ();
    }

  sntrup761_enc (ct, k1, pk, rngctx, rngfun);

  if (memcmp (ct, xct, SNTRUP761_CIPHERTEXT_SIZE)
      || memcmp (k1, xk, SNTRUP761_SIZE))
    {
      printf ("\nnstrup761_enc:\nct = ");
      print_hex (sizeof ct, ct);
      printf ("\nk1 = ");
      print_hex (sizeof k1, k1);
      abort ();
    }

  sntrup761_dec (k2, ct, sk);

  if (memcmp (k2, xk, SNTRUP761_SIZE))
    {
      printf ("\nnstrup761_dec:\nk2 = ");
      print_hex (sizeof k2, k2);
      abort ();
    }

  if (memcmp (k1, k2, SNTRUP761_SIZE))
    {
      printf ("\nsntrup761 k1 != k2\n");
      abort ();
    }
}

static char *H(const char* in)
{
  static const unsigned char TBL[] = {
    0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  58,  59,  60,  61,
    62,  63,  64,  10,  11,  12,  13,  14,  15,  71,  72,  73,  74,  75,
    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,



Josefsson               Expires 12 November 2023               [Page 37]

Internet-Draft                  sntrup761                       May 2023


    90,  91,  92,  93,  94,  95,  96,  10,  11,  12,  13,  14,  15
  };
  static const unsigned char *LOOKUP = TBL - 48;
  const char* end = in + strlen (in);
  char *out, *tmp;

  out = tmp = malloc (strlen (in));
  if (!out)
    abort();

  while(in < end)
    *(tmp++) = LOOKUP[*(in++)] << 4 | LOOKUP[*(in++)];

  return out;
}

void
main (void)
{
  struct drbg_ctr_aes256_ctx rng;
  uint8_t seed_material[DRBG_CTR_AES256_SEED_SIZE];
  uint8_t tmp[DRBG_CTR_AES256_SEED_SIZE];
  size_t i;

  for (i = 0; i < DRBG_CTR_AES256_SEED_SIZE; i++)
    seed_material[i] = i;

  drbg_ctr_aes256_init (&rng, seed_material);

  drbg_ctr_aes256_random (&rng, DRBG_CTR_AES256_SEED_SIZE, tmp);
  if (memcmp (tmp,
              H ("061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479"
                 "D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1"),
              DRBG_CTR_AES256_SEED_SIZE))
    {
      printf ("drbg_ctr_aes256 = ");
      print_hex (DRBG_CTR_AES256_SEED_SIZE, tmp);
      abort ();
    }

  drbg_ctr_aes256_init (&rng,
                        H ("061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479"
                           "D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1"));
  test_sntrup (&rng, (sntrup761_random_func *) drbg_ctr_aes256_random,
               H ("36C969CF1008A6AA9551A784941C65A9BF68C2DC33FA36B5"
                  "D266B25171B346679F2D22BF3123A79C790D6DEC68E1BC44"
                  "420A6824F5357C78E3C336FEE0551E620DCB975F563682A3"
                  "12A3353B521C727F57CABED0C3228F09317CAE8B58158EBF"



Josefsson               Expires 12 November 2023               [Page 38]

Internet-Draft                  sntrup761                       May 2023


                  "5B26BDC6E6365AA601ACAD2ABD37F5830D0BBFE355705C0A"
                  "62B76A5C910AD04E55E5DAD749C7393D2E2E8AB643E62E47"
                  "57AD2201CAA33203F53B4A9D4757E7274D72BDB036A31D7D"
                  "E11E5D1C66CF3059F33B6A2972C1E1D9C9FB2AEBC78B2C05"
                  "5D48D79C3A7C996C08B7DEF0791CDE895053885D8DA1D254"
                  "EE19C090AF34F4720B0B77139108D8498982FEAB0B54934C"
                  "EE3DCD24B049F981A84C928028A64A26CDF87052313C3E50"
                  "B2E1F539394502433C0962996C3599189B15174281B6595B"
                  "567B8C4CD80902860E613AE1906A55607CBF0E11AD6C0C0D"
                  "F38C006A5F535FA6E6FB49D10B78B9CB6473BF0630518DB6"
                  "FDECFD70DED201C7E35FFB3BB78D8AEC181F6DE960C316FE"
                  "354B7CC69E8048201965AAFEF4EA3F808737FF45255A1779"
                  "DE57A4B68DB587263D7B7F6CB07D8B01224DD291237EFD9C"
                  "01676E30154A2A7D60174536580FE64EFEDDA5FB42C13ED8"
                  "C5768A3CBCAE7A2343B3128CD5C1C663A07C7DC0E1E2642C"
                  "0D9A02F349C964154A6C4308D8ECF30F47E9A81EED2A32A2"
                  "BB44DFC36A28A66AE77BB139FA416B6327EEFE33632469CC"
                  "C21229587573C4F7752CE1CC79CA0C6BDA08CD79E25720D2"
                  "D9092EA2AB13F31E9A3AF1C69FC6379D8E2AD2B87B514C81"
                  "7A087338B7B0736B8954DE9223225B40079C92601248C14B"
                  "2104901E74F849D9EEE9F5636C1DAD6031AB477C573197E7"
                  "EB6CE535D9F0F69183DD9DF5521595E5C9E98D846CE08AA6"
                  "55B70CC0D8041401929690298F645D9112DBB03B189CDB1F"
                  "CF4D512F6874B409BF55EE1CC284A05B698B8818F043C259"
                  "1C9F4ABA29CF4259915D6A0BE71B6B93963C618CBB567838"
                  "E5EADE6500DE9AD250083A01EB3EB44C00EECB2B0F874CDA"
                  "165FAA6524CA13D435C938DB9469292FE97283C69222107E"
                  "A2F9EFCA1B6D41DCA5B149B2A8CC2244A1BC54261CC11742"
                  "ACD27B7F2352C33FB83FE143386479D78D6D5C3E51684B60"
                  "A56714182449C94327139B0289B9BDE0AE3FEF319FE2C605"
                  "AB5507C894D2C2761A3BD3EA30F4BA928F9F23303061617E"
                  "2F042DCF229AFF2C9345A6B3CDCF90D3E3BCC3A1110C8561"
                  "6BD585C31CDE3E69ADC12A18BFA5797DF0543435A7C874A8"
                  "ACF3786FCCBA4A6CEAA65E5666230AA7206AE78EB1B98CB5"
                  "236508E6357E18CCCFAEC5693532BE4EE38022C48FE94F62"
                  "B0293A088BF4D737F48748F23BCB338B58B4D666AD3C64E9"
                  "ECD07265F971B07AF716D4A5B719C3F5FE35744734CBA543"
                  "0381661E372B6F6510D61B11E4697A1A961589949DBA53B5"
                  "BC5BDB76FA09324387D799536506182EFF7078034B34E1DD"
                  "D2612B0A40E7F1A294FBA869DA2E46C4C36BB08C7E9BEF09"
                  "A94459E8FC2D3CC579D15284DF1F19EF77E03041511ACC39"
                  "BF9CA8AC8DE6A0E5EEA0BBD4289B6DAE38E9E82EB50A0397"
                  "B3EE6C52FBDC7DEEA2C376825E89016C859B09488548BF76"
                  "CA62D696DF94A61E8F0E13C69EE816CE5AA2768987B0A782"
                  "D74C673EC005"),
               H ("55565515155545556569159955A255545545616145059455"
                  "6556915055895615548852955456550098544995555AA546"
                  "5400A5555558956510A6515596559665996A449154154144"



Josefsson               Expires 12 November 2023               [Page 39]

Internet-Draft                  sntrup761                       May 2023


                  "655655555511056241569549446269405555551656659555"
                  "55A515915559565915656515424040891954545669558590"
                  "64258656285054569505A6A9569494466614155801155650"
                  "55485955259049A5545525455504526A195455554185525A"
                  "899625525556582484644514556589656258515459150185"
                  "08154A51A0448959112A286212608A52911A949119A28956"
                  "64165900A861541A200A52104029544600425A5A1198101A"
                  "1A50A094A551425A484959A1506486A618555A8990561502"
                  "9622A2A46696A2A6595A46682622525050489A8040562808"
                  "168156854185026540A1059A94AAA291811948A259816991"
                  "110951802409AA5A2A06290092451446655608404096898A"
                  "A56220562285150891914066110A0905A841044865042A26"
                  "88AA12441AAA46064669155555A2109659299922820036C9"
                  "69CF1008A6AA9551A784941C65A9BF68C2DC33FA36B5D266"
                  "B25171B346679F2D22BF3123A79C790D6DEC68E1BC44420A"
                  "6824F5357C78E3C336FEE0551E620DCB975F563682A312A3"
                  "353B521C727F57CABED0C3228F09317CAE8B58158EBF5B26"
                  "BDC6E6365AA601ACAD2ABD37F5830D0BBFE355705C0A62B7"
                  "6A5C910AD04E55E5DAD749C7393D2E2E8AB643E62E4757AD"
                  "2201CAA33203F53B4A9D4757E7274D72BDB036A31D7DE11E"
                  "5D1C66CF3059F33B6A2972C1E1D9C9FB2AEBC78B2C055D48"
                  "D79C3A7C996C08B7DEF0791CDE895053885D8DA1D254EE19"
                  "C090AF34F4720B0B77139108D8498982FEAB0B54934CEE3D"
                  "CD24B049F981A84C928028A64A26CDF87052313C3E50B2E1"
                  "F539394502433C0962996C3599189B15174281B6595B567B"
                  "8C4CD80902860E613AE1906A55607CBF0E11AD6C0C0DF38C"
                  "006A5F535FA6E6FB49D10B78B9CB6473BF0630518DB6FDEC"
                  "FD70DED201C7E35FFB3BB78D8AEC181F6DE960C316FE354B"
                  "7CC69E8048201965AAFEF4EA3F808737FF45255A1779DE57"
                  "A4B68DB587263D7B7F6CB07D8B01224DD291237EFD9C0167"
                  "6E30154A2A7D60174536580FE64EFEDDA5FB42C13ED8C576"
                  "8A3CBCAE7A2343B3128CD5C1C663A07C7DC0E1E2642C0D9A"
                  "02F349C964154A6C4308D8ECF30F47E9A81EED2A32A2BB44"
                  "DFC36A28A66AE77BB139FA416B6327EEFE33632469CCC212"
                  "29587573C4F7752CE1CC79CA0C6BDA08CD79E25720D2D909"
                  "2EA2AB13F31E9A3AF1C69FC6379D8E2AD2B87B514C817A08"
                  "7338B7B0736B8954DE9223225B40079C92601248C14B2104"
                  "901E74F849D9EEE9F5636C1DAD6031AB477C573197E7EB6C"
                  "E535D9F0F69183DD9DF5521595E5C9E98D846CE08AA655B7"
                  "0CC0D8041401929690298F645D9112DBB03B189CDB1FCF4D"
                  "512F6874B409BF55EE1CC284A05B698B8818F043C2591C9F"
                  "4ABA29CF4259915D6A0BE71B6B93963C618CBB567838E5EA"
                  "DE6500DE9AD250083A01EB3EB44C00EECB2B0F874CDA165F"
                  "AA6524CA13D435C938DB9469292FE97283C69222107EA2F9"
                  "EFCA1B6D41DCA5B149B2A8CC2244A1BC54261CC11742ACD2"
                  "7B7F2352C33FB83FE143386479D78D6D5C3E51684B60A567"
                  "14182449C94327139B0289B9BDE0AE3FEF319FE2C605AB55"
                  "07C894D2C2761A3BD3EA30F4BA928F9F23303061617E2F04"



Josefsson               Expires 12 November 2023               [Page 40]

Internet-Draft                  sntrup761                       May 2023


                  "2DCF229AFF2C9345A6B3CDCF90D3E3BCC3A1110C85616BD5"
                  "85C31CDE3E69ADC12A18BFA5797DF0543435A7C874A8ACF3"
                  "786FCCBA4A6CEAA65E5666230AA7206AE78EB1B98CB52365"
                  "08E6357E18CCCFAEC5693532BE4EE38022C48FE94F62B029"
                  "3A088BF4D737F48748F23BCB338B58B4D666AD3C64E9ECD0"
                  "7265F971B07AF716D4A5B719C3F5FE35744734CBA5430381"
                  "661E372B6F6510D61B11E4697A1A961589949DBA53B5BC5B"
                  "DB76FA09324387D799536506182EFF7078034B34E1DDD261"
                  "2B0A40E7F1A294FBA869DA2E46C4C36BB08C7E9BEF09A944"
                  "59E8FC2D3CC579D15284DF1F19EF77E03041511ACC39BF9C"
                  "A8AC8DE6A0E5EEA0BBD4289B6DAE38E9E82EB50A0397B3EE"
                  "6C52FBDC7DEEA2C376825E89016C859B09488548BF76CA62"
                  "D696DF94A61E8F0E13C69EE816CE5AA2768987B0A782D74C"
                  "673EC0059FA532AE97F8BDF90F90130926654FB8B469D772"
                  "049D72A8375CD8459D06CC1B90633EB3A899685D21491B50"
                  "62A9FC73FB6E878D7A73198EFA0B569D9CE665CE126FFDC9"
                  "862EB00D11F457A7995555F7C92011C24E1CEC45C270FB5F"
                  "121F08177F97FC3F631C0EF86A92E99D557FB69A0F6FCD8B"
                  "1C0EF94AA7429B3A8A11614D847202D3D04A98313FC0D63A"
                  "BF9FD75CA321C879458BF8837B7E74CCF5179C7714FA9800"
                  "D1821EE3F9639D28136B7910872631F85AE7B6DD289E0103"
                  "4217210859D4E53C65487CE38AFF621DA76BA1C4E2E77ED5"
                  "380B47B8D983CCB5BB793E"),
               H ("84F327D38929039EF84366AB796A96E6CC268454D5AD8D05"
                  "410D3E969B6D228B6CED2CBAD7BAB3B4B7EE453747D3331D"
                  "43B21CD2ECC3BF557D696E81773EE69F687FE1F61E63742A"
                  "F913A35418575467118409D4FFDBBAC5CA062DFF3F04D761"
                  "54D17EC34212DEBFCA967A91E461F73786D949D6A9765140"
                  "B9DC7849639A487058F45DDA919576090D35E783804BA7B8"
                  "B33B5C6A8C1EBB7C39F042696CF9F2B624D26EA5D6D10148"
                  "9E242CC35126B573928B6B8BF9945269AD22E7DA70CCB7DC"
                  "374F75641978D5F6D5F540A1169EB098570A7CFD65C9257C"
                  "4C196F42C6DA4F4466D8F11A17C6A75A9BDD45B5AC77A836"
                  "7B005ED22141A81B995A19E4DC9E6743B4B45E0329E7A00D"
                  "3FF90C7A917CDC9CA75A34FFFDD9A321751B5C8B2AB9E1EA"
                  "037CF45C04B412A97F52E7C6D66508456D9117961257B4F5"
                  "0BB9F500DE99B6F061C377D44F495D711AB2ED3E88CCF14D"
                  "F10F8C60BD00E29CD83AD160FAEF2984FAC7E897CBB8CDA1"
                  "44D50E4C1AD20238A2617598DA6EFE786AA82E0931B0B5D1"
                  "A7FA024B856353AFAEDB0A1150A42DA182353CE5A00403BB"
                  "6B7A13EFFC14B0FD97E1117302ED8A66FAAED88B43B34CFC"
                  "73CB33E49A4C34D0BFDEE2FEADC2B4C8BB1EC41215586FC6"
                  "6550D496373305B99CEE254EAC71D3CDAC689A777062ACAE"
                  "65B031B5A1A973835BE6A4BB061F178531C45DE3B33E7763"
                  "B483621821E037FE5EF48FD971D8D2BEFDA63250E9B1181D"
                  "8B8086BED9CDA8CDE6644CDE8EBF7C1F1038AFE798A2A4C4"
                  "92B603B7F4F8805D0FDF19D8274888CEBEC3043CC9ACF024"
                  "BD30D8B0D28D311985930110386598775CF84E0848B11E09"



Josefsson               Expires 12 November 2023               [Page 41]

Internet-Draft                  sntrup761                       May 2023


                  "0905A65F56142FC17D2573536FC51E7D5B2E0FF7B0947115"
                  "5008561156FBAEC215031ED0D844EB14D6C609173355FFF8"
                  "AE22C6E5BCCD19B2832E5FBE625C2C0E516E1369D1FCF49A"
                  "5FDBAF8CF572F04317DB8ED70EE1605B96D077B4F054C72B"
                  "139F5BCAA5BB627E39BE5BCC97AF922C5E70835BD918281B"
                  "95E557FC86A43C75980A0D9F0F9162F230014CD867DD07DB"
                  "23260934546C04499D6B8627B8D5DEC73FA45327F8498352"
                  "9BAF3AA10E885724FE76055099D136CCAACC159B4CE38784"
                  "404CC9B04723910F990AF77C64D42A29D784FC897955758F"
                  "1D2A12BB7C6F6A8E5B94EFA740F662CF0DA2D099C61EE1CC"
                  "6B661A64F0887B805AF53C7B64C4456DAF228582C1B2212A"
                  "8F718E56DF6B72D7EFA0C5D26582CE96AEFCE13CB2830C3F"
                  "B32E5115AACC20D3A335F7A4C12E0CD1DE532D8D9D42D69B"
                  "C2D0BE0AC7DF3B8F416B9A53DB261C47272725A8A8829867"
                  "8351B42103219092076B6ECE744D993388A8F2C475079CB8"
                  "BC4DC492A4797147C01EA3508225826F7A3D32BF502B0F45"
                  "52F36FC9F6FB91E82DB1949338B45436EC0FF63B53F900F2"
                  "7F8147D420F93D33C83794980E94143FD361F944DDB56D31"
                  "14EE974C96A155"),
               H ("344CA5E25F6DA5EA95E4A695B1C5446ECA9859334532E4A9"
                  "537669F012C743A2"));

  drbg_ctr_aes256_init (&rng,
                        H ("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55"
                           "B22E75BF57BB556AC81ADDE6AEEB4A5A875C3BFCADFA958F"));
  test_sntrup (&rng, (sntrup761_random_func *) drbg_ctr_aes256_random,
               H ("D2530F125EE5F208B1976A66BCBC917161F6929E636BA8C7"
                  "3470DE18065F6057528D718744E9248DFFF6BB55C188CEAC"
                  "B9419863C3C456B46A21354834ADA6B2132C67747C9EE70D"
                  "02560268EE650E56C84BCE6A6700C5E612999110E53A866A"
                  "E6B4F778230367B8B886C4FEC089C6267F91C7F24D6CE53C"
                  "754D9CCCDD25756D76CD211D5954F0E8A11343679C1F692C"
                  "E5C0D0E42A02381144E1E0201B6F49F00628A86E09918488"
                  "BC3E1E1071561700544C2CE50F4B7BAE4757CA7A0DD0A221"
                  "260E0574D1F8F81AF072FCBA8061B5B8BB450FDCC6732D35"
                  "CDBBBC4EF1798EA7E263BCF369059EED3A86E2C61C72CBFC"
                  "D69521C3A1FD4868AF5638148043162B8B6E39F82B56D6C9"
                  "C7724807F623C06CC08FF619F7961EC972B1BD2856F87D5E"
                  "6940DC15B9575264A4AB0CA229C5B02C9AA5BB8DA2BD8EB0"
                  "9A7A5E824C2D666A17C4845CA9530F3A5E45BE5A380B83C8"
                  "1B3965180C706E2CC9ABF4DC8A1559CCF176EFD0FAAD1B8E"
                  "184AAA08E24CA6F5D070E040D64CD65A1628E99F3BACAB5A"
                  "7206B5C7D1F7D282651448E259A839E128774530C931C4E4"
                  "E6F60AB9CDEB645AA24012C3A0983750C04914C59E34AF67"
                  "B9128CE906AD162D70E582C42E21898EF8023A9D1BC3B5F5"
                  "BDE6415CD168F1DE726A2ECB27C48A73356FBBEE8F405A6F"
                  "8C34F8F5A864C109045618B03FBFDCBAFD8BC93465863407"
                  "0D40E5C62A03F9B544C325BCC56D8C70D67DA39879356E98"



Josefsson               Expires 12 November 2023               [Page 42]

Internet-Draft                  sntrup761                       May 2023


                  "71B016A0CCF3FE1C6AB941B69417FF514B616C9CFE9EA066"
                  "FBB4B081B25D584E40430B0950A7EBFBFA9B4E4EE003F297"
                  "BA668F7139F26F218026DC9BFDBBBE6FD1CDE03CAC981429"
                  "9126E8CBDAFFD54101E07C09B65B88C9743B85C464E44C72"
                  "56F506F07BC7D3877E2578D589CD2001E5124C9E647FAC21"
                  "34B34E74DC188478E538BBFB750B47600191C51B71F18460"
                  "CECD5FBDABAA48D6DD6DBE7E26CEF9498220379F1FF25AFA"
                  "CA60CEFFA408CEB677E4CAFB3A43B3E5FAA5B731EA608A94"
                  "5EDF645136ADC77B07DB34E191D9E786ED7CFD97E2330548"
                  "FFE021997E2E8B774E4A5F1666A91F05D471874E765DF42C"
                  "7C3D9EF37CD946E0D69C9EA83CEC9B1AA41A25F1A3A458C9"
                  "935CBC7D294B64D628DA7F1B0FA4F24E6375DF31AE82815F"
                  "5DFF4ACD0DD9BD8A8740CB92633D1E000191B837021F143F"
                  "64B08388A78B9A0F55FE7B824FA9D4E85709EAC46EAB5B24"
                  "C46BBC2D1D8D39FEC8BA130EB68A7F55769606F07CB7B8CA"
                  "0AD99739C68A365E415983B964F1F2D261145057B7A76D72"
                  "300AD49D9FFFFFFE9C41BD48B82F8450274C6C25DCECE61D"
                  "4C443FEE0D3C359FDD4E4409AD607AE7A707B83B8629134D"
                  "ACCBD54C618EEF0B2F04E848F7B62C494DEC89F2830BACED"
                  "B3B876670309B36F7D70BE0219F5D05A3C1E5BB58B1CF053"
                  "FE92D2E3F934AA2047F963172E04B7457FED3956C08A705C"
                  "9C441F1FEE07E05344C63817F5DA7F298D5323BF88FB490E"
                  "1C628015ECD09C5D89978EB42A2DFD32E0820B005BDB60FF"
                  "FB15EBE1A123C6107530FE48C72C925FB85465749EF1A46C"
                  "6BA7F0F31D911D9E78608DAA64EC87CB3C82ABEC988FA365"
                  "6734A038FB5A3F072B7E9E9F383227EA3D5ACE37A6A5536B"
                  "9E3AA926E900"),
               H ("645159996555659148569656954105506019451895595549"
                  "848669516585555885215216015254544569A65216995559"
                  "854155141511559254664659655555655555614616559508"
                  "95559696596565645699555A1596555A966566614655A409"
                  "51559554669590615659A551555125556595551955569915"
                  "A5614089A15501582951945A155586595555556541104911"
                  "69A0115656649156245559244155A584145650516445A555"
                  "555955485655455681166469511A59642155555501990285"
                  "891A514062416580150298400062840021A908660880A85A"
                  "28008958212528A0A604218026444A2AA5452A9522051201"
                  "99055041A99129298A989A895206621800648A98A8806986"
                  "4862A4651468A14114268209A55249440A89519065056895"
                  "86229848816266852198A2A2096459194A55040291048662"
                  "2949A09448210A94429A444126A4A66A0AA18921A4A54514"
                  "595A81248446A86601905118A2850492910185041822A524"
                  "22565641A195969068850240588648408A14990A6801D253"
                  "0F125EE5F208B1976A66BCBC917161F6929E636BA8C73470"
                  "DE18065F6057528D718744E9248DFFF6BB55C188CEACB941"
                  "9863C3C456B46A21354834ADA6B2132C67747C9EE70D0256"
                  "0268EE650E56C84BCE6A6700C5E612999110E53A866AE6B4"
                  "F778230367B8B886C4FEC089C6267F91C7F24D6CE53C754D"



Josefsson               Expires 12 November 2023               [Page 43]

Internet-Draft                  sntrup761                       May 2023


                  "9CCCDD25756D76CD211D5954F0E8A11343679C1F692CE5C0"
                  "D0E42A02381144E1E0201B6F49F00628A86E09918488BC3E"
                  "1E1071561700544C2CE50F4B7BAE4757CA7A0DD0A221260E"
                  "0574D1F8F81AF072FCBA8061B5B8BB450FDCC6732D35CDBB"
                  "BC4EF1798EA7E263BCF369059EED3A86E2C61C72CBFCD695"
                  "21C3A1FD4868AF5638148043162B8B6E39F82B56D6C9C772"
                  "4807F623C06CC08FF619F7961EC972B1BD2856F87D5E6940"
                  "DC15B9575264A4AB0CA229C5B02C9AA5BB8DA2BD8EB09A7A"
                  "5E824C2D666A17C4845CA9530F3A5E45BE5A380B83C81B39"
                  "65180C706E2CC9ABF4DC8A1559CCF176EFD0FAAD1B8E184A"
                  "AA08E24CA6F5D070E040D64CD65A1628E99F3BACAB5A7206"
                  "B5C7D1F7D282651448E259A839E128774530C931C4E4E6F6"
                  "0AB9CDEB645AA24012C3A0983750C04914C59E34AF67B912"
                  "8CE906AD162D70E582C42E21898EF8023A9D1BC3B5F5BDE6"
                  "415CD168F1DE726A2ECB27C48A73356FBBEE8F405A6F8C34"
                  "F8F5A864C109045618B03FBFDCBAFD8BC934658634070D40"
                  "E5C62A03F9B544C325BCC56D8C70D67DA39879356E9871B0"
                  "16A0CCF3FE1C6AB941B69417FF514B616C9CFE9EA066FBB4"
                  "B081B25D584E40430B0950A7EBFBFA9B4E4EE003F297BA66"
                  "8F7139F26F218026DC9BFDBBBE6FD1CDE03CAC9814299126"
                  "E8CBDAFFD54101E07C09B65B88C9743B85C464E44C7256F5"
                  "06F07BC7D3877E2578D589CD2001E5124C9E647FAC2134B3"
                  "4E74DC188478E538BBFB750B47600191C51B71F18460CECD"
                  "5FBDABAA48D6DD6DBE7E26CEF9498220379F1FF25AFACA60"
                  "CEFFA408CEB677E4CAFB3A43B3E5FAA5B731EA608A945EDF"
                  "645136ADC77B07DB34E191D9E786ED7CFD97E2330548FFE0"
                  "21997E2E8B774E4A5F1666A91F05D471874E765DF42C7C3D"
                  "9EF37CD946E0D69C9EA83CEC9B1AA41A25F1A3A458C9935C"
                  "BC7D294B64D628DA7F1B0FA4F24E6375DF31AE82815F5DFF"
                  "4ACD0DD9BD8A8740CB92633D1E000191B837021F143F64B0"
                  "8388A78B9A0F55FE7B824FA9D4E85709EAC46EAB5B24C46B"
                  "BC2D1D8D39FEC8BA130EB68A7F55769606F07CB7B8CA0AD9"
                  "9739C68A365E415983B964F1F2D261145057B7A76D72300A"
                  "D49D9FFFFFFE9C41BD48B82F8450274C6C25DCECE61D4C44"
                  "3FEE0D3C359FDD4E4409AD607AE7A707B83B8629134DACCB"
                  "D54C618EEF0B2F04E848F7B62C494DEC89F2830BACEDB3B8"
                  "76670309B36F7D70BE0219F5D05A3C1E5BB58B1CF053FE92"
                  "D2E3F934AA2047F963172E04B7457FED3956C08A705C9C44"
                  "1F1FEE07E05344C63817F5DA7F298D5323BF88FB490E1C62"
                  "8015ECD09C5D89978EB42A2DFD32E0820B005BDB60FFFB15"
                  "EBE1A123C6107530FE48C72C925FB85465749EF1A46C6BA7"
                  "F0F31D911D9E78608DAA64EC87CB3C82ABEC988FA3656734"
                  "A038FB5A3F072B7E9E9F383227EA3D5ACE37A6A5536B9E3A"
                  "A926E900B736895EF729F2159BA82A0D090B0D4A26FFC467"
                  "511911F39D3EC248467A576EE1F8DCA10DD0C3BE961080D9"
                  "25B823AD9538477F258DD445AF4872DFDEB8E4A819DDE314"
                  "766683246379B03AA738907ED3671359999FF298C4A44133"
                  "417821912013E792C90D939815BC3AEBB565E1D6B42BB356"



Josefsson               Expires 12 November 2023               [Page 44]

Internet-Draft                  sntrup761                       May 2023


                  "CC6A6C79EB6D640001C9D0ED847B4D39B2C38FC2123609EF"
                  "94608B766EBEB91DD12D228123D29D14C1B4169D8417D260"
                  "54304B5C900E5CF78159735D0FFA15B691369BC66811A9F1"
                  "1ADB3ED280E3151830BAC71B6E5EE77238F632911067ED8C"
                  "525887CF983CFE4A2572D3"),
               H ("8CE9955F6DC23A0E49D9B263C43026609612696FD84D37DF"
                  "A1192BA0D9412D2125E25A7C64209A92E5F1C6F170D5C4C8"
                  "91D5050E336F628544620D6B0A9C5058DBBB51C4F540AE3C"
                  "19BD941E7CD3105A7BCD1774FF05B0B65E310A1D6F88253C"
                  "FA36C2E7F34130B14613B188D8B9D6C9BE040CE2446F33F7"
                  "5E2A61AF7D7C11FFF54505F1E1EEE49172234915D722599C"
                  "6BD77D0BCEBEC69435BAC571A194939861CE3ED3960C0FD0"
                  "FDB8D7CBD272659BBB881C29A70ECB62388062C4ABB2A565"
                  "A0D9CE73E23E9CA7D589DE524E8289762499F867697003DB"
                  "B87E1657313D05E5E8E7C7FF407DF7931EB6842C82521936"
                  "9E92D2E65E29CFCF31DCD0F40706AF8B4F70D9E8AF6147AC"
                  "7D8B1900773D9EE2CE6C4EEC38C4FF44F2E397D95684CE5E"
                  "E6FD5FE4975216819BAE496D2CE888A6F630FE448A4872BB"
                  "C5164A70A33A9988A3C4AEA17A8688346191CD4BE2F8D021"
                  "CC97D5A20BFFFFC628ED6F267145C41BCFB83161C2326294"
                  "3B530DF4BD4B6BDD85D78A2DAF0499B8DE97AFE6191AFD3A"
                  "35E8268A4D08EC55DBA8BEC15BDE4F823D4B3C62F7990EF7"
                  "A655D03DD4897F640ABDD60D58A3244F745CEA09ACCDD56D"
                  "E4D8F08F43025E084E91634E25FC7B39BCAFFC1803E8D480"
                  "6786548263D6BF8D8ACC84FA9A01D786F438FEDB811DF9FC"
                  "0EFFCF9C6A787B17228B260D6ACCE43075E7F80CC57C6821"
                  "01CD9CDF12B2D3F931AAAE1A2434AAE772C11CCEE49E2503"
                  "DAE5CBC98E41F6AD6E885B1F011E9883CE078B33D99FC414"
                  "71CCA14FC0DC12789464CE92B93A08E8F3D25822827A0827"
                  "3FA2E5114909F0D4A378A482F0EBDF781991E1E28B3F72CA"
                  "D3886575FF7E59F2B8607CE314D8292E27C1D6187EC5C76C"
                  "B1347185D760D69F91B7F455DDE52257B03CBB9845B78867"
                  "EABAA28535B6DEA69D14693666B1E978503F65412C5AFF4A"
                  "FEC1F537C416EAC390D5EEA0C3B4694DB4FAB95CAC381D12"
                  "F42F176F27A4BEE0C0A0A458B51E5C71D82724593014C154"
                  "30BECDBB472659D91B093192590A43A6E56BB6AD3C6C5BAA"
                  "7AA49D888E1CFA656200680A31ECDB99A4B0109133523653"
                  "D9769A945ADEC3890734841B94ACC62A8AB0805F0E9E9E3B"
                  "4471552DA0B5E78935C149E3D4DFCB20F75BDA04A86611B4"
                  "192BC6AF2B5C3C1C4424E40E8AF9E1A7A3E57B9AACA0B730"
                  "585931386329C19846D1BF091084C12380D7B2FB3348E7BC"
                  "25EF9BC39FEBA174B8FC9A191A11C345E0E3CB3170593928"
                  "429F0729BB96D771BAFCB84633B80377658EBB5866631AE2"
                  "EBAE05940AFDBA13F34A0341E923EA2C31F11E2A1A421C45"
                  "22AB50153A77B7950834CBF23A16D01462A0FCD270BCF66B"
                  "9F6E0A5A39F5989D75643DFC8EC4D5B051AE94C6DB74D777"
                  "9C54016EAD109D10AC190B07816CDCD2B8EC9BC596090DF0"
                  "0FE23B4E862FE7E0D7EBCBF6B2A1A565435DA662CB34489B"



Josefsson               Expires 12 November 2023               [Page 45]

Internet-Draft                  sntrup761                       May 2023


                  "B570286BA114F8"),
               H ("16C15126F734E51268BA916CE3B39A72E171AE79B8C2B6A6"
                  "8B34AB0DC5621B7E"));
}

                               Figure 7

6.4.  drbg-ctr.h

   This is the C header file for the DRBG-CTR-AES256 implementation,
   used by the sntrup761-test.c test driver to reproduce test vectors.

   #ifndef DRBG_CTR_H
   #define DRBG_CTR_H

   #include <string.h>
   #include <stdint.h>

   #include "aes256_ecb.h"

   #define DRBG_CTR_AES256_SEED_SIZE (AES_BLOCK_SIZE + AES256_KEY_SIZE)

   struct drbg_ctr_aes256_ctx
   {
     uint8_t K[AES256_KEY_SIZE];
     uint8_t V[AES_BLOCK_SIZE];
   };

   /* Initialize using DRBG_CTR_AES256_SEED_SIZE bytes of
      SEED_MATERIAL.  */
   void
   drbg_ctr_aes256_init (struct drbg_ctr_aes256_ctx *ctx,
                         uint8_t *seed_material);

   /* Output N bytes of random data into DST.  */
   void
   drbg_ctr_aes256_random (struct drbg_ctr_aes256_ctx *ctx,
                           size_t n, uint8_t *dst);

   #endif /* DRBG_CTR_H */

                                  Figure 8

6.5.  drbg-ctr.c

   This is the C implementation file for the DRBG-CTR-AES256
   implementation, used by the sntrup761-test.c test driver to reproduce
   test vectors.



Josefsson               Expires 12 November 2023               [Page 46]

Internet-Draft                  sntrup761                       May 2023


#include "drbg-ctr.h"

#include <string.h>

static void memxor(uint8_t *dst, const uint8_t *src, size_t n)
{
  size_t i;
  for (i = 0; i < n; i++)
    dst[i] ^= src[i];
}

static void increment (uint8_t *V)
{
  size_t i;

  for (i = AES_BLOCK_SIZE - 1; i > 0; i--)
    {
      if (V[i] == 0xFF)
        V[i] = 0;
      else
        {
          V[i]++;
          break;
        }
    }
}

static void
drbg_ctr_aes256_update (uint8_t *Key, uint8_t *V, uint8_t *provided_data)
{
  uint8_t tmp[DRBG_CTR_AES256_SEED_SIZE];

  increment (V);
  aes256_encrypt (Key, tmp, V);

  increment (V);
  aes256_encrypt (Key, tmp + AES_BLOCK_SIZE, V);

  increment (V);
  aes256_encrypt (Key, tmp + 2 * AES_BLOCK_SIZE, V);

  if (provided_data)
    memxor (tmp, provided_data, 48);

  memcpy (Key, tmp, AES256_KEY_SIZE);
  memcpy (V, tmp + AES256_KEY_SIZE, AES_BLOCK_SIZE);
}




Josefsson               Expires 12 November 2023               [Page 47]

Internet-Draft                  sntrup761                       May 2023


void
drbg_ctr_aes256_init (struct drbg_ctr_aes256_ctx *ctx, uint8_t *seed_material)
{
  memset (ctx->K, 0, AES256_KEY_SIZE);
  memset (ctx->V, 0, AES_BLOCK_SIZE);

  drbg_ctr_aes256_update (ctx->K, ctx->V, seed_material);
}

void
drbg_ctr_aes256_random (struct drbg_ctr_aes256_ctx *ctx,
                        size_t n, uint8_t *dst)
{
  while (n >= AES_BLOCK_SIZE)
    {
      increment (ctx->V);
      aes256_encrypt (ctx->K, dst, ctx->V);
      dst += AES_BLOCK_SIZE;
      n -= AES_BLOCK_SIZE;
    }

  if (n > 0)
    {
      uint8_t block[AES_BLOCK_SIZE];

      increment (ctx->V);
      aes256_encrypt (ctx->K, block, ctx->V);
      memcpy (dst, block, n);
    }

  drbg_ctr_aes256_update (ctx->K, ctx->V, NULL);
}

                               Figure 9

6.6.  sha512.h, sha512.c, aes256_ecb.h, aes256_ecb.c

   These are helper code used by the sntrup761-test.c test driver to
   reproduce test vectors, and require OpenSSL but you may substitute
   your own implementation of these cryptographic primitives.

   extern void crypto_hash_sha512 (unsigned char *out,
                                   const unsigned char *in,
                                   unsigned long long inlen);

                                 Figure 10





Josefsson               Expires 12 November 2023               [Page 48]

Internet-Draft                  sntrup761                       May 2023


   #include <openssl/sha.h>
   #include "sha512.h"

   void crypto_hash_sha512 (unsigned char *out,
                            const unsigned char *in,
                            unsigned long long inlen)
   {
     SHA512(in, inlen, out);
   }

                                 Figure 11

   #define AES_BLOCK_SIZE 16
   #define AES256_KEY_SIZE 32

   extern void
   aes256_encrypt (const unsigned char *key,
                   unsigned char *out,
                   const unsigned char *in);

                                 Figure 12

  #include <openssl/evp.h>

  #include "aes256_ecb.h"

  void
  aes256_encrypt (const unsigned char *key,
                  unsigned char *out,
                  const unsigned char *in)
  {
    EVP_CIPHER_CTX *ctx;
    int len;

    if(!(ctx = EVP_CIPHER_CTX_new()))
      abort();

    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
      abort();

    if(1 != EVP_EncryptUpdate(ctx, out, &len, in, AES_BLOCK_SIZE))
      abort();

    EVP_CIPHER_CTX_free(ctx);
  }

                                Figure 13




Josefsson               Expires 12 November 2023               [Page 49]

Internet-Draft                  sntrup761                       May 2023


7.  Streamlined NTRU Prime: Test Vectors

   For brevity, below is a reduced number of test vectors, for full
   examples see [sntrup761kat].

   count = 0

   seed = "061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479"
          "D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1"

   pk   = "36C969CF1008A6AA9551A784941C65A9BF68C2DC33FA36B5"
          "D266B25171B346679F2D22BF3123A79C790D6DEC68E1BC44"
          "420A6824F5357C78E3C336FEE0551E620DCB975F563682A3"
          "12A3353B521C727F57CABED0C3228F09317CAE8B58158EBF"
          "5B26BDC6E6365AA601ACAD2ABD37F5830D0BBFE355705C0A"
          "62B76A5C910AD04E55E5DAD749C7393D2E2E8AB643E62E47"
          "57AD2201CAA33203F53B4A9D4757E7274D72BDB036A31D7D"
          "E11E5D1C66CF3059F33B6A2972C1E1D9C9FB2AEBC78B2C05"
          "5D48D79C3A7C996C08B7DEF0791CDE895053885D8DA1D254"
          "EE19C090AF34F4720B0B77139108D8498982FEAB0B54934C"
          "EE3DCD24B049F981A84C928028A64A26CDF87052313C3E50"
          "B2E1F539394502433C0962996C3599189B15174281B6595B"
          "567B8C4CD80902860E613AE1906A55607CBF0E11AD6C0C0D"
          "F38C006A5F535FA6E6FB49D10B78B9CB6473BF0630518DB6"
          "FDECFD70DED201C7E35FFB3BB78D8AEC181F6DE960C316FE"
          "354B7CC69E8048201965AAFEF4EA3F808737FF45255A1779"
          "DE57A4B68DB587263D7B7F6CB07D8B01224DD291237EFD9C"
          "01676E30154A2A7D60174536580FE64EFEDDA5FB42C13ED8"
          "C5768A3CBCAE7A2343B3128CD5C1C663A07C7DC0E1E2642C"
          "0D9A02F349C964154A6C4308D8ECF30F47E9A81EED2A32A2"
          "BB44DFC36A28A66AE77BB139FA416B6327EEFE33632469CC"
          "C21229587573C4F7752CE1CC79CA0C6BDA08CD79E25720D2"
          "D9092EA2AB13F31E9A3AF1C69FC6379D8E2AD2B87B514C81"
          "7A087338B7B0736B8954DE9223225B40079C92601248C14B"
          "2104901E74F849D9EEE9F5636C1DAD6031AB477C573197E7"
          "EB6CE535D9F0F69183DD9DF5521595E5C9E98D846CE08AA6"
          "55B70CC0D8041401929690298F645D9112DBB03B189CDB1F"
          "CF4D512F6874B409BF55EE1CC284A05B698B8818F043C259"
          "1C9F4ABA29CF4259915D6A0BE71B6B93963C618CBB567838"
          "E5EADE6500DE9AD250083A01EB3EB44C00EECB2B0F874CDA"
          "165FAA6524CA13D435C938DB9469292FE97283C69222107E"
          "A2F9EFCA1B6D41DCA5B149B2A8CC2244A1BC54261CC11742"
          "ACD27B7F2352C33FB83FE143386479D78D6D5C3E51684B60"
          "A56714182449C94327139B0289B9BDE0AE3FEF319FE2C605"
          "AB5507C894D2C2761A3BD3EA30F4BA928F9F23303061617E"
          "2F042DCF229AFF2C9345A6B3CDCF90D3E3BCC3A1110C8561"
          "6BD585C31CDE3E69ADC12A18BFA5797DF0543435A7C874A8"
          "ACF3786FCCBA4A6CEAA65E5666230AA7206AE78EB1B98CB5"



Josefsson               Expires 12 November 2023               [Page 50]

Internet-Draft                  sntrup761                       May 2023


          "236508E6357E18CCCFAEC5693532BE4EE38022C48FE94F62"
          "B0293A088BF4D737F48748F23BCB338B58B4D666AD3C64E9"
          "ECD07265F971B07AF716D4A5B719C3F5FE35744734CBA543"
          "0381661E372B6F6510D61B11E4697A1A961589949DBA53B5"
          "BC5BDB76FA09324387D799536506182EFF7078034B34E1DD"
          "D2612B0A40E7F1A294FBA869DA2E46C4C36BB08C7E9BEF09"
          "A94459E8FC2D3CC579D15284DF1F19EF77E03041511ACC39"
          "BF9CA8AC8DE6A0E5EEA0BBD4289B6DAE38E9E82EB50A0397"
          "B3EE6C52FBDC7DEEA2C376825E89016C859B09488548BF76"
          "CA62D696DF94A61E8F0E13C69EE816CE5AA2768987B0A782"
          "D74C673EC005"

   sk   = "55565515155545556569159955A255545545616145059455"
          "6556915055895615548852955456550098544995555AA546"
          "5400A5555558956510A6515596559665996A449154154144"
          "655655555511056241569549446269405555551656659555"
          "55A515915559565915656515424040891954545669558590"
          "64258656285054569505A6A9569494466614155801155650"
          "55485955259049A5545525455504526A195455554185525A"
          "899625525556582484644514556589656258515459150185"
          "08154A51A0448959112A286212608A52911A949119A28956"
          "64165900A861541A200A52104029544600425A5A1198101A"
          "1A50A094A551425A484959A1506486A618555A8990561502"
          "9622A2A46696A2A6595A46682622525050489A8040562808"
          "168156854185026540A1059A94AAA291811948A259816991"
          "110951802409AA5A2A06290092451446655608404096898A"
          "A56220562285150891914066110A0905A841044865042A26"
          "88AA12441AAA46064669155555A2109659299922820036C9"
          "69CF1008A6AA9551A784941C65A9BF68C2DC33FA36B5D266"
          "B25171B346679F2D22BF3123A79C790D6DEC68E1BC44420A"
          "6824F5357C78E3C336FEE0551E620DCB975F563682A312A3"
          "353B521C727F57CABED0C3228F09317CAE8B58158EBF5B26"
          "BDC6E6365AA601ACAD2ABD37F5830D0BBFE355705C0A62B7"
          "6A5C910AD04E55E5DAD749C7393D2E2E8AB643E62E4757AD"
          "2201CAA33203F53B4A9D4757E7274D72BDB036A31D7DE11E"
          "5D1C66CF3059F33B6A2972C1E1D9C9FB2AEBC78B2C055D48"
          "D79C3A7C996C08B7DEF0791CDE895053885D8DA1D254EE19"
          "C090AF34F4720B0B77139108D8498982FEAB0B54934CEE3D"
          "CD24B049F981A84C928028A64A26CDF87052313C3E50B2E1"
          "F539394502433C0962996C3599189B15174281B6595B567B"
          "8C4CD80902860E613AE1906A55607CBF0E11AD6C0C0DF38C"
          "006A5F535FA6E6FB49D10B78B9CB6473BF0630518DB6FDEC"
          "FD70DED201C7E35FFB3BB78D8AEC181F6DE960C316FE354B"
          "7CC69E8048201965AAFEF4EA3F808737FF45255A1779DE57"
          "A4B68DB587263D7B7F6CB07D8B01224DD291237EFD9C0167"
          "6E30154A2A7D60174536580FE64EFEDDA5FB42C13ED8C576"
          "8A3CBCAE7A2343B3128CD5C1C663A07C7DC0E1E2642C0D9A"
          "02F349C964154A6C4308D8ECF30F47E9A81EED2A32A2BB44"



Josefsson               Expires 12 November 2023               [Page 51]

Internet-Draft                  sntrup761                       May 2023


          "DFC36A28A66AE77BB139FA416B6327EEFE33632469CCC212"
          "29587573C4F7752CE1CC79CA0C6BDA08CD79E25720D2D909"
          "2EA2AB13F31E9A3AF1C69FC6379D8E2AD2B87B514C817A08"
          "7338B7B0736B8954DE9223225B40079C92601248C14B2104"
          "901E74F849D9EEE9F5636C1DAD6031AB477C573197E7EB6C"
          "E535D9F0F69183DD9DF5521595E5C9E98D846CE08AA655B7"
          "0CC0D8041401929690298F645D9112DBB03B189CDB1FCF4D"
          "512F6874B409BF55EE1CC284A05B698B8818F043C2591C9F"
          "4ABA29CF4259915D6A0BE71B6B93963C618CBB567838E5EA"
          "DE6500DE9AD250083A01EB3EB44C00EECB2B0F874CDA165F"
          "AA6524CA13D435C938DB9469292FE97283C69222107EA2F9"
          "EFCA1B6D41DCA5B149B2A8CC2244A1BC54261CC11742ACD2"
          "7B7F2352C33FB83FE143386479D78D6D5C3E51684B60A567"
          "14182449C94327139B0289B9BDE0AE3FEF319FE2C605AB55"
          "07C894D2C2761A3BD3EA30F4BA928F9F23303061617E2F04"
          "2DCF229AFF2C9345A6B3CDCF90D3E3BCC3A1110C85616BD5"
          "85C31CDE3E69ADC12A18BFA5797DF0543435A7C874A8ACF3"
          "786FCCBA4A6CEAA65E5666230AA7206AE78EB1B98CB52365"
          "08E6357E18CCCFAEC5693532BE4EE38022C48FE94F62B029"
          "3A088BF4D737F48748F23BCB338B58B4D666AD3C64E9ECD0"
          "7265F971B07AF716D4A5B719C3F5FE35744734CBA5430381"
          "661E372B6F6510D61B11E4697A1A961589949DBA53B5BC5B"
          "DB76FA09324387D799536506182EFF7078034B34E1DDD261"
          "2B0A40E7F1A294FBA869DA2E46C4C36BB08C7E9BEF09A944"
          "59E8FC2D3CC579D15284DF1F19EF77E03041511ACC39BF9C"
          "A8AC8DE6A0E5EEA0BBD4289B6DAE38E9E82EB50A0397B3EE"
          "6C52FBDC7DEEA2C376825E89016C859B09488548BF76CA62"
          "D696DF94A61E8F0E13C69EE816CE5AA2768987B0A782D74C"
          "673EC0059FA532AE97F8BDF90F90130926654FB8B469D772"
          "049D72A8375CD8459D06CC1B90633EB3A899685D21491B50"
          "62A9FC73FB6E878D7A73198EFA0B569D9CE665CE126FFDC9"
          "862EB00D11F457A7995555F7C92011C24E1CEC45C270FB5F"
          "121F08177F97FC3F631C0EF86A92E99D557FB69A0F6FCD8B"
          "1C0EF94AA7429B3A8A11614D847202D3D04A98313FC0D63A"
          "BF9FD75CA321C879458BF8837B7E74CCF5179C7714FA9800"
          "D1821EE3F9639D28136B7910872631F85AE7B6DD289E0103"
          "4217210859D4E53C65487CE38AFF621DA76BA1C4E2E77ED5"
          "380B47B8D983CCB5BB793E"

   ct   = "84F327D38929039EF84366AB796A96E6CC268454D5AD8D05"
          "410D3E969B6D228B6CED2CBAD7BAB3B4B7EE453747D3331D"
          "43B21CD2ECC3BF557D696E81773EE69F687FE1F61E63742A"
          "F913A35418575467118409D4FFDBBAC5CA062DFF3F04D761"
          "54D17EC34212DEBFCA967A91E461F73786D949D6A9765140"
          "B9DC7849639A487058F45DDA919576090D35E783804BA7B8"
          "B33B5C6A8C1EBB7C39F042696CF9F2B624D26EA5D6D10148"
          "9E242CC35126B573928B6B8BF9945269AD22E7DA70CCB7DC"
          "374F75641978D5F6D5F540A1169EB098570A7CFD65C9257C"



Josefsson               Expires 12 November 2023               [Page 52]

Internet-Draft                  sntrup761                       May 2023


          "4C196F42C6DA4F4466D8F11A17C6A75A9BDD45B5AC77A836"
          "7B005ED22141A81B995A19E4DC9E6743B4B45E0329E7A00D"
          "3FF90C7A917CDC9CA75A34FFFDD9A321751B5C8B2AB9E1EA"
          "037CF45C04B412A97F52E7C6D66508456D9117961257B4F5"
          "0BB9F500DE99B6F061C377D44F495D711AB2ED3E88CCF14D"
          "F10F8C60BD00E29CD83AD160FAEF2984FAC7E897CBB8CDA1"
          "44D50E4C1AD20238A2617598DA6EFE786AA82E0931B0B5D1"
          "A7FA024B856353AFAEDB0A1150A42DA182353CE5A00403BB"
          "6B7A13EFFC14B0FD97E1117302ED8A66FAAED88B43B34CFC"
          "73CB33E49A4C34D0BFDEE2FEADC2B4C8BB1EC41215586FC6"
          "6550D496373305B99CEE254EAC71D3CDAC689A777062ACAE"
          "65B031B5A1A973835BE6A4BB061F178531C45DE3B33E7763"
          "B483621821E037FE5EF48FD971D8D2BEFDA63250E9B1181D"
          "8B8086BED9CDA8CDE6644CDE8EBF7C1F1038AFE798A2A4C4"
          "92B603B7F4F8805D0FDF19D8274888CEBEC3043CC9ACF024"
          "BD30D8B0D28D311985930110386598775CF84E0848B11E09"
          "0905A65F56142FC17D2573536FC51E7D5B2E0FF7B0947115"
          "5008561156FBAEC215031ED0D844EB14D6C609173355FFF8"
          "AE22C6E5BCCD19B2832E5FBE625C2C0E516E1369D1FCF49A"
          "5FDBAF8CF572F04317DB8ED70EE1605B96D077B4F054C72B"
          "139F5BCAA5BB627E39BE5BCC97AF922C5E70835BD918281B"
          "95E557FC86A43C75980A0D9F0F9162F230014CD867DD07DB"
          "23260934546C04499D6B8627B8D5DEC73FA45327F8498352"
          "9BAF3AA10E885724FE76055099D136CCAACC159B4CE38784"
          "404CC9B04723910F990AF77C64D42A29D784FC897955758F"
          "1D2A12BB7C6F6A8E5B94EFA740F662CF0DA2D099C61EE1CC"
          "6B661A64F0887B805AF53C7B64C4456DAF228582C1B2212A"
          "8F718E56DF6B72D7EFA0C5D26582CE96AEFCE13CB2830C3F"
          "B32E5115AACC20D3A335F7A4C12E0CD1DE532D8D9D42D69B"
          "C2D0BE0AC7DF3B8F416B9A53DB261C47272725A8A8829867"
          "8351B42103219092076B6ECE744D993388A8F2C475079CB8"
          "BC4DC492A4797147C01EA3508225826F7A3D32BF502B0F45"
          "52F36FC9F6FB91E82DB1949338B45436EC0FF63B53F900F2"
          "7F8147D420F93D33C83794980E94143FD361F944DDB56D31"
          "14EE974C96A155"

   ss   = "344CA5E25F6DA5EA95E4A695B1C5446ECA9859334532E4A9"
          "537669F012C743A2"

   count = 1

   seed = "D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55"
          "B22E75BF57BB556AC81ADDE6AEEB4A5A875C3BFCADFA958F"

   pk   = "D2530F125EE5F208B1976A66BCBC917161F6929E636BA8C7"
          "3470DE18065F6057528D718744E9248DFFF6BB55C188CEAC"
          "B9419863C3C456B46A21354834ADA6B2132C67747C9EE70D"
          "02560268EE650E56C84BCE6A6700C5E612999110E53A866A"



Josefsson               Expires 12 November 2023               [Page 53]

Internet-Draft                  sntrup761                       May 2023


          "E6B4F778230367B8B886C4FEC089C6267F91C7F24D6CE53C"
          "754D9CCCDD25756D76CD211D5954F0E8A11343679C1F692C"
          "E5C0D0E42A02381144E1E0201B6F49F00628A86E09918488"
          "BC3E1E1071561700544C2CE50F4B7BAE4757CA7A0DD0A221"
          "260E0574D1F8F81AF072FCBA8061B5B8BB450FDCC6732D35"
          "CDBBBC4EF1798EA7E263BCF369059EED3A86E2C61C72CBFC"
          "D69521C3A1FD4868AF5638148043162B8B6E39F82B56D6C9"
          "C7724807F623C06CC08FF619F7961EC972B1BD2856F87D5E"
          "6940DC15B9575264A4AB0CA229C5B02C9AA5BB8DA2BD8EB0"
          "9A7A5E824C2D666A17C4845CA9530F3A5E45BE5A380B83C8"
          "1B3965180C706E2CC9ABF4DC8A1559CCF176EFD0FAAD1B8E"
          "184AAA08E24CA6F5D070E040D64CD65A1628E99F3BACAB5A"
          "7206B5C7D1F7D282651448E259A839E128774530C931C4E4"
          "E6F60AB9CDEB645AA24012C3A0983750C04914C59E34AF67"
          "B9128CE906AD162D70E582C42E21898EF8023A9D1BC3B5F5"
          "BDE6415CD168F1DE726A2ECB27C48A73356FBBEE8F405A6F"
          "8C34F8F5A864C109045618B03FBFDCBAFD8BC93465863407"
          "0D40E5C62A03F9B544C325BCC56D8C70D67DA39879356E98"
          "71B016A0CCF3FE1C6AB941B69417FF514B616C9CFE9EA066"
          "FBB4B081B25D584E40430B0950A7EBFBFA9B4E4EE003F297"
          "BA668F7139F26F218026DC9BFDBBBE6FD1CDE03CAC981429"
          "9126E8CBDAFFD54101E07C09B65B88C9743B85C464E44C72"
          "56F506F07BC7D3877E2578D589CD2001E5124C9E647FAC21"
          "34B34E74DC188478E538BBFB750B47600191C51B71F18460"
          "CECD5FBDABAA48D6DD6DBE7E26CEF9498220379F1FF25AFA"
          "CA60CEFFA408CEB677E4CAFB3A43B3E5FAA5B731EA608A94"
          "5EDF645136ADC77B07DB34E191D9E786ED7CFD97E2330548"
          "FFE021997E2E8B774E4A5F1666A91F05D471874E765DF42C"
          "7C3D9EF37CD946E0D69C9EA83CEC9B1AA41A25F1A3A458C9"
          "935CBC7D294B64D628DA7F1B0FA4F24E6375DF31AE82815F"
          "5DFF4ACD0DD9BD8A8740CB92633D1E000191B837021F143F"
          "64B08388A78B9A0F55FE7B824FA9D4E85709EAC46EAB5B24"
          "C46BBC2D1D8D39FEC8BA130EB68A7F55769606F07CB7B8CA"
          "0AD99739C68A365E415983B964F1F2D261145057B7A76D72"
          "300AD49D9FFFFFFE9C41BD48B82F8450274C6C25DCECE61D"
          "4C443FEE0D3C359FDD4E4409AD607AE7A707B83B8629134D"
          "ACCBD54C618EEF0B2F04E848F7B62C494DEC89F2830BACED"
          "B3B876670309B36F7D70BE0219F5D05A3C1E5BB58B1CF053"
          "FE92D2E3F934AA2047F963172E04B7457FED3956C08A705C"
          "9C441F1FEE07E05344C63817F5DA7F298D5323BF88FB490E"
          "1C628015ECD09C5D89978EB42A2DFD32E0820B005BDB60FF"
          "FB15EBE1A123C6107530FE48C72C925FB85465749EF1A46C"
          "6BA7F0F31D911D9E78608DAA64EC87CB3C82ABEC988FA365"
          "6734A038FB5A3F072B7E9E9F383227EA3D5ACE37A6A5536B"
          "9E3AA926E900"

   sk   = "645159996555659148569656954105506019451895595549"
          "848669516585555885215216015254544569A65216995559"



Josefsson               Expires 12 November 2023               [Page 54]

Internet-Draft                  sntrup761                       May 2023


          "854155141511559254664659655555655555614616559508"
          "95559696596565645699555A1596555A966566614655A409"
          "51559554669590615659A551555125556595551955569915"
          "A5614089A15501582951945A155586595555556541104911"
          "69A0115656649156245559244155A584145650516445A555"
          "555955485655455681166469511A59642155555501990285"
          "891A514062416580150298400062840021A908660880A85A"
          "28008958212528A0A604218026444A2AA5452A9522051201"
          "99055041A99129298A989A895206621800648A98A8806986"
          "4862A4651468A14114268209A55249440A89519065056895"
          "86229848816266852198A2A2096459194A55040291048662"
          "2949A09448210A94429A444126A4A66A0AA18921A4A54514"
          "595A81248446A86601905118A2850492910185041822A524"
          "22565641A195969068850240588648408A14990A6801D253"
          "0F125EE5F208B1976A66BCBC917161F6929E636BA8C73470"
          "DE18065F6057528D718744E9248DFFF6BB55C188CEACB941"
          "9863C3C456B46A21354834ADA6B2132C67747C9EE70D0256"
          "0268EE650E56C84BCE6A6700C5E612999110E53A866AE6B4"
          "F778230367B8B886C4FEC089C6267F91C7F24D6CE53C754D"
          "9CCCDD25756D76CD211D5954F0E8A11343679C1F692CE5C0"
          "D0E42A02381144E1E0201B6F49F00628A86E09918488BC3E"
          "1E1071561700544C2CE50F4B7BAE4757CA7A0DD0A221260E"
          "0574D1F8F81AF072FCBA8061B5B8BB450FDCC6732D35CDBB"
          "BC4EF1798EA7E263BCF369059EED3A86E2C61C72CBFCD695"
          "21C3A1FD4868AF5638148043162B8B6E39F82B56D6C9C772"
          "4807F623C06CC08FF619F7961EC972B1BD2856F87D5E6940"
          "DC15B9575264A4AB0CA229C5B02C9AA5BB8DA2BD8EB09A7A"
          "5E824C2D666A17C4845CA9530F3A5E45BE5A380B83C81B39"
          "65180C706E2CC9ABF4DC8A1559CCF176EFD0FAAD1B8E184A"
          "AA08E24CA6F5D070E040D64CD65A1628E99F3BACAB5A7206"
          "B5C7D1F7D282651448E259A839E128774530C931C4E4E6F6"
          "0AB9CDEB645AA24012C3A0983750C04914C59E34AF67B912"
          "8CE906AD162D70E582C42E21898EF8023A9D1BC3B5F5BDE6"
          "415CD168F1DE726A2ECB27C48A73356FBBEE8F405A6F8C34"
          "F8F5A864C109045618B03FBFDCBAFD8BC934658634070D40"
          "E5C62A03F9B544C325BCC56D8C70D67DA39879356E9871B0"
          "16A0CCF3FE1C6AB941B69417FF514B616C9CFE9EA066FBB4"
          "B081B25D584E40430B0950A7EBFBFA9B4E4EE003F297BA66"
          "8F7139F26F218026DC9BFDBBBE6FD1CDE03CAC9814299126"
          "E8CBDAFFD54101E07C09B65B88C9743B85C464E44C7256F5"
          "06F07BC7D3877E2578D589CD2001E5124C9E647FAC2134B3"
          "4E74DC188478E538BBFB750B47600191C51B71F18460CECD"
          "5FBDABAA48D6DD6DBE7E26CEF9498220379F1FF25AFACA60"
          "CEFFA408CEB677E4CAFB3A43B3E5FAA5B731EA608A945EDF"
          "645136ADC77B07DB34E191D9E786ED7CFD97E2330548FFE0"
          "21997E2E8B774E4A5F1666A91F05D471874E765DF42C7C3D"
          "9EF37CD946E0D69C9EA83CEC9B1AA41A25F1A3A458C9935C"
          "BC7D294B64D628DA7F1B0FA4F24E6375DF31AE82815F5DFF"



Josefsson               Expires 12 November 2023               [Page 55]

Internet-Draft                  sntrup761                       May 2023


          "4ACD0DD9BD8A8740CB92633D1E000191B837021F143F64B0"
          "8388A78B9A0F55FE7B824FA9D4E85709EAC46EAB5B24C46B"
          "BC2D1D8D39FEC8BA130EB68A7F55769606F07CB7B8CA0AD9"
          "9739C68A365E415983B964F1F2D261145057B7A76D72300A"
          "D49D9FFFFFFE9C41BD48B82F8450274C6C25DCECE61D4C44"
          "3FEE0D3C359FDD4E4409AD607AE7A707B83B8629134DACCB"
          "D54C618EEF0B2F04E848F7B62C494DEC89F2830BACEDB3B8"
          "76670309B36F7D70BE0219F5D05A3C1E5BB58B1CF053FE92"
          "D2E3F934AA2047F963172E04B7457FED3956C08A705C9C44"
          "1F1FEE07E05344C63817F5DA7F298D5323BF88FB490E1C62"
          "8015ECD09C5D89978EB42A2DFD32E0820B005BDB60FFFB15"
          "EBE1A123C6107530FE48C72C925FB85465749EF1A46C6BA7"
          "F0F31D911D9E78608DAA64EC87CB3C82ABEC988FA3656734"
          "A038FB5A3F072B7E9E9F383227EA3D5ACE37A6A5536B9E3A"
          "A926E900B736895EF729F2159BA82A0D090B0D4A26FFC467"
          "511911F39D3EC248467A576EE1F8DCA10DD0C3BE961080D9"
          "25B823AD9538477F258DD445AF4872DFDEB8E4A819DDE314"
          "766683246379B03AA738907ED3671359999FF298C4A44133"
          "417821912013E792C90D939815BC3AEBB565E1D6B42BB356"
          "CC6A6C79EB6D640001C9D0ED847B4D39B2C38FC2123609EF"
          "94608B766EBEB91DD12D228123D29D14C1B4169D8417D260"
          "54304B5C900E5CF78159735D0FFA15B691369BC66811A9F1"
          "1ADB3ED280E3151830BAC71B6E5EE77238F632911067ED8C"
          "525887CF983CFE4A2572D3"

   ct   = "8CE9955F6DC23A0E49D9B263C43026609612696FD84D37DF"
          "A1192BA0D9412D2125E25A7C64209A92E5F1C6F170D5C4C8"
          "91D5050E336F628544620D6B0A9C5058DBBB51C4F540AE3C"
          "19BD941E7CD3105A7BCD1774FF05B0B65E310A1D6F88253C"
          "FA36C2E7F34130B14613B188D8B9D6C9BE040CE2446F33F7"
          "5E2A61AF7D7C11FFF54505F1E1EEE49172234915D722599C"
          "6BD77D0BCEBEC69435BAC571A194939861CE3ED3960C0FD0"
          "FDB8D7CBD272659BBB881C29A70ECB62388062C4ABB2A565"
          "A0D9CE73E23E9CA7D589DE524E8289762499F867697003DB"
          "B87E1657313D05E5E8E7C7FF407DF7931EB6842C82521936"
          "9E92D2E65E29CFCF31DCD0F40706AF8B4F70D9E8AF6147AC"
          "7D8B1900773D9EE2CE6C4EEC38C4FF44F2E397D95684CE5E"
          "E6FD5FE4975216819BAE496D2CE888A6F630FE448A4872BB"
          "C5164A70A33A9988A3C4AEA17A8688346191CD4BE2F8D021"
          "CC97D5A20BFFFFC628ED6F267145C41BCFB83161C2326294"
          "3B530DF4BD4B6BDD85D78A2DAF0499B8DE97AFE6191AFD3A"
          "35E8268A4D08EC55DBA8BEC15BDE4F823D4B3C62F7990EF7"
          "A655D03DD4897F640ABDD60D58A3244F745CEA09ACCDD56D"
          "E4D8F08F43025E084E91634E25FC7B39BCAFFC1803E8D480"
          "6786548263D6BF8D8ACC84FA9A01D786F438FEDB811DF9FC"
          "0EFFCF9C6A787B17228B260D6ACCE43075E7F80CC57C6821"
          "01CD9CDF12B2D3F931AAAE1A2434AAE772C11CCEE49E2503"
          "DAE5CBC98E41F6AD6E885B1F011E9883CE078B33D99FC414"



Josefsson               Expires 12 November 2023               [Page 56]

Internet-Draft                  sntrup761                       May 2023


          "71CCA14FC0DC12789464CE92B93A08E8F3D25822827A0827"
          "3FA2E5114909F0D4A378A482F0EBDF781991E1E28B3F72CA"
          "D3886575FF7E59F2B8607CE314D8292E27C1D6187EC5C76C"
          "B1347185D760D69F91B7F455DDE52257B03CBB9845B78867"
          "EABAA28535B6DEA69D14693666B1E978503F65412C5AFF4A"
          "FEC1F537C416EAC390D5EEA0C3B4694DB4FAB95CAC381D12"
          "F42F176F27A4BEE0C0A0A458B51E5C71D82724593014C154"
          "30BECDBB472659D91B093192590A43A6E56BB6AD3C6C5BAA"
          "7AA49D888E1CFA656200680A31ECDB99A4B0109133523653"
          "D9769A945ADEC3890734841B94ACC62A8AB0805F0E9E9E3B"
          "4471552DA0B5E78935C149E3D4DFCB20F75BDA04A86611B4"
          "192BC6AF2B5C3C1C4424E40E8AF9E1A7A3E57B9AACA0B730"
          "585931386329C19846D1BF091084C12380D7B2FB3348E7BC"
          "25EF9BC39FEBA174B8FC9A191A11C345E0E3CB3170593928"
          "429F0729BB96D771BAFCB84633B80377658EBB5866631AE2"
          "EBAE05940AFDBA13F34A0341E923EA2C31F11E2A1A421C45"
          "22AB50153A77B7950834CBF23A16D01462A0FCD270BCF66B"
          "9F6E0A5A39F5989D75643DFC8EC4D5B051AE94C6DB74D777"
          "9C54016EAD109D10AC190B07816CDCD2B8EC9BC596090DF0"
          "0FE23B4E862FE7E0D7EBCBF6B2A1A565435DA662CB34489B"
          "B570286BA114F8"

   ss   = "16C15126F734E51268BA916CE3B39A72E171AE79B8C2B6A6"
          "8B34AB0DC5621B7E"

                                 Figure 14

8.  Acknowledgements

   The majority of this document was derived from [NTRUPrime]
   [NTRUPrimePQCS].

9.  IANA Considerations

   This document has no IANA actions.

10.  Security Considerations

   See [NTRUPrime] and [NTRUPrimePQCS] for discussions.

   Streamlined NTRU Prime sntrup761 is aiming for the standard goal of
   IND-CCA2 security, is widely implemented with good performance on a
   wide range of architectures, and has been studied by researchers for
   several years.  However new cryptographic primitives should be
   introduced and trusted conservatively, and new research findings may
   be published at any time that may warrant implementation
   reconsiderations.




Josefsson               Expires 12 November 2023               [Page 57]

Internet-Draft                  sntrup761                       May 2023


   The increase in communication size and computational requirements may
   be a concern for restricted computational devices, which would then
   not be able to take advantage of the improved security properties
   offer by this work.

11.  References

11.1.  Normative References

   [NTRUPrimePQCS]
              Bernstein, D.J., Brumley, B. B., Chen,, M.,
              Chuengsatiansup, C., Lange, T., Marotzke, A., Peng, B.,
              Tuveri, N., Vredendaal, C. V., and B. Yang, "NTRU Prime:
              round 3", WWW https://ntruprime.cr.yp.to/nist/ntruprime-
              20201007.pdf, October 2020.

11.2.  Informative References

   [NTRUPrime]
              Bernstein, D.J., Chuengsatiansup, C., Lange, T., and C.
              van Vredendaal, "NTRU Prime: reducing attack surface at
              low cost", WWW https://ntruprime.cr.yp.to/ntruprime-
              20170816.pdf, August 2017.

   [SageMath] "SageMath", WWW https://www.sagemath.org/.

   [sntrup761kat]
              "sntrup761 kat_kem.rsp", WWW 
              https://ntruprime.cr.yp.to/nist/ntruprime-
              20201007/KAT/kem/sntrup761/kat_kem.rsp.html.

Author's Address

   Simon Josefsson
   Email: simon@josefsson.org
   URI:   https://blog.josefsson.org/















Josefsson               Expires 12 November 2023               [Page 58]