1*e7be843bSPierre Pronchery /* 2*e7be843bSPierre Pronchery * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. 3*e7be843bSPierre Pronchery * 4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5*e7be843bSPierre Pronchery * this file except in compliance with the License. You can obtain a copy 6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at 7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html 8*e7be843bSPierre Pronchery */ 9*e7be843bSPierre Pronchery 10*e7be843bSPierre Pronchery #ifndef PROV_ML_COMMON_CODECS_H 11*e7be843bSPierre Pronchery # define PROV_ML_COMMON_CODECS_H 12*e7be843bSPierre Pronchery # pragma once 13*e7be843bSPierre Pronchery 14*e7be843bSPierre Pronchery # include <openssl/e_os2.h> 15*e7be843bSPierre Pronchery # include "crypto/ml_dsa.h" 16*e7be843bSPierre Pronchery # include "prov/provider_ctx.h" 17*e7be843bSPierre Pronchery 18*e7be843bSPierre Pronchery /*- 19*e7be843bSPierre Pronchery * The DER ASN.1 encoding of ML-DSA and ML-KEM public keys prepends 22 bytes 20*e7be843bSPierre Pronchery * to the encoded public key: 21*e7be843bSPierre Pronchery * 22*e7be843bSPierre Pronchery * - 4 byte outer sequence tag and length 23*e7be843bSPierre Pronchery * - 2 byte algorithm sequence tag and length 24*e7be843bSPierre Pronchery * - 2 byte algorithm OID tag and length 25*e7be843bSPierre Pronchery * - 9 byte algorithm OID (from NIST CSOR OID arc) 26*e7be843bSPierre Pronchery * - 4 byte bit string tag and length 27*e7be843bSPierre Pronchery * - 1 bitstring lead byte 28*e7be843bSPierre Pronchery */ 29*e7be843bSPierre Pronchery # define ML_COMMON_SPKI_OVERHEAD 22 30*e7be843bSPierre Pronchery typedef struct { 31*e7be843bSPierre Pronchery const uint8_t asn1_prefix[ML_COMMON_SPKI_OVERHEAD]; 32*e7be843bSPierre Pronchery } ML_COMMON_SPKI_FMT; 33*e7be843bSPierre Pronchery 34*e7be843bSPierre Pronchery /*- 35*e7be843bSPierre Pronchery * For each parameter set we support a few PKCS#8 input formats, three 36*e7be843bSPierre Pronchery * corresponding to the "either or both" variants of: 37*e7be843bSPierre Pronchery * 38*e7be843bSPierre Pronchery * ML-DSA-PrivateKey ::= CHOICE { 39*e7be843bSPierre Pronchery * seed [0] IMPLICIT OCTET STRING (SIZE (32)), 40*e7be843bSPierre Pronchery * expandedKey OCTET STRING (SIZE (2560 | 4032 | 4896)), 41*e7be843bSPierre Pronchery * both SEQUENCE { 42*e7be843bSPierre Pronchery * seed OCTET STRING (SIZE (32)), 43*e7be843bSPierre Pronchery * expandedKey OCTET STRING (SIZE (2560 | 4032 | 4896)) } } 44*e7be843bSPierre Pronchery * 45*e7be843bSPierre Pronchery * ML-KEM-PrivateKey ::= CHOICE { 46*e7be843bSPierre Pronchery * seed [0] IMPLICIT OCTET STRING (SIZE (64)), 47*e7be843bSPierre Pronchery * expandedKey OCTET STRING (SIZE (1632 | 2400 | 3168)), 48*e7be843bSPierre Pronchery * both SEQUENCE { 49*e7be843bSPierre Pronchery * seed OCTET STRING (SIZE (64)), 50*e7be843bSPierre Pronchery * expandedKey OCTET STRING SIZE ((1632 | 2400 | 3168)) } } 51*e7be843bSPierre Pronchery * 52*e7be843bSPierre Pronchery * one more for a historical OQS encoding: 53*e7be843bSPierre Pronchery * 54*e7be843bSPierre Pronchery * - OQS private + public key: OCTET STRING 55*e7be843bSPierre Pronchery * (The public key is ignored, just as with PKCS#8 v2.) 56*e7be843bSPierre Pronchery * 57*e7be843bSPierre Pronchery * and two more that are the minimal IETF non-ASN.1 seed encoding: 58*e7be843bSPierre Pronchery * 59*e7be843bSPierre Pronchery * - Bare seed (just the 32 or 64 bytes) 60*e7be843bSPierre Pronchery * - Bare priv (just the key bytes) 61*e7be843bSPierre Pronchery * 62*e7be843bSPierre Pronchery * A length of zero means that particular field is absent. 63*e7be843bSPierre Pronchery * 64*e7be843bSPierre Pronchery * The p8_shift is 0 when the top-level tag+length occupy four bytes, 2 when 65*e7be843bSPierre Pronchery * they occupy two by†es, and 4 when no tag is used at all. 66*e7be843bSPierre Pronchery */ 67*e7be843bSPierre Pronchery #define NUM_PKCS8_FORMATS 6 68*e7be843bSPierre Pronchery 69*e7be843bSPierre Pronchery typedef struct { 70*e7be843bSPierre Pronchery const char *p8_name; /* Format name */ 71*e7be843bSPierre Pronchery size_t p8_bytes; /* Total P8 encoding length */ 72*e7be843bSPierre Pronchery int p8_shift; /* 4 - (top-level tag + len) */ 73*e7be843bSPierre Pronchery uint32_t p8_magic; /* The tag + len value */ 74*e7be843bSPierre Pronchery uint16_t seed_magic; /* Interior tag + len for the seed */ 75*e7be843bSPierre Pronchery size_t seed_offset; /* Seed offset from start */ 76*e7be843bSPierre Pronchery size_t seed_length; /* Seed bytes */ 77*e7be843bSPierre Pronchery uint32_t priv_magic; /* Interior tag + len for the key */ 78*e7be843bSPierre Pronchery size_t priv_offset; /* Key offset from start */ 79*e7be843bSPierre Pronchery size_t priv_length; /* Key bytes */ 80*e7be843bSPierre Pronchery size_t pub_offset; /* Pubkey offset */ 81*e7be843bSPierre Pronchery size_t pub_length; /* Pubkey bytes */ 82*e7be843bSPierre Pronchery } ML_COMMON_PKCS8_FMT; 83*e7be843bSPierre Pronchery 84*e7be843bSPierre Pronchery typedef struct { 85*e7be843bSPierre Pronchery const ML_COMMON_SPKI_FMT *spkifmt; 86*e7be843bSPierre Pronchery const ML_COMMON_PKCS8_FMT *p8fmt; 87*e7be843bSPierre Pronchery } ML_COMMON_CODEC; 88*e7be843bSPierre Pronchery 89*e7be843bSPierre Pronchery typedef struct { 90*e7be843bSPierre Pronchery const ML_COMMON_PKCS8_FMT *fmt; 91*e7be843bSPierre Pronchery int pref; 92*e7be843bSPierre Pronchery } ML_COMMON_PKCS8_FMT_PREF; 93*e7be843bSPierre Pronchery 94*e7be843bSPierre Pronchery ML_COMMON_PKCS8_FMT_PREF * 95*e7be843bSPierre Pronchery ossl_ml_common_pkcs8_fmt_order(const char *algorithm_name, 96*e7be843bSPierre Pronchery const ML_COMMON_PKCS8_FMT *p8fmt, 97*e7be843bSPierre Pronchery const char *direction, const char *formats); 98*e7be843bSPierre Pronchery #endif 99