Skip to content

Commit c075896

Browse files
committed
XXX: openpgp: Implement SLHDSA{128s,128f,256s} using OpenSSL.
- Requires support in rust-openssl that is not yet merged. See sfackler/rust-openssl#2405 - Fixes #1175.
1 parent 749170f commit c075896

File tree

1 file changed

+164
-1
lines changed

1 file changed

+164
-1
lines changed

openpgp/src/crypto/backend/openssl/asymmetric.rs

Lines changed: 164 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ impl Asymmetric for super::Backend {
3636
// XXX: Would be better to have a runtime test.
3737
MLDSA65_Ed25519 | MLDSA87_Ed448 =>
3838
openssl::version::number() >= 0x3_05_00_00_0,
39+
// XXX: Would be better to have a runtime test.
3940
SLHDSA128s | SLHDSA128f | SLHDSA256s =>
40-
false,
41+
openssl::version::number() >= 0x3_05_00_00_0,
4142
MLKEM768_X25519 | MLKEM1024_X448 =>
4243
false,
4344
ElGamalEncrypt | ElGamalEncryptSign |
@@ -275,6 +276,168 @@ impl Asymmetric for super::Backend {
275276
Ok(ctx.verify(digest, &signature[..])?)
276277
}
277278

279+
fn slhdsa128s_generate_key() -> Result<(Protected, [u8; 32])> {
280+
use openssl::pkey_slh_dsa::{PKeySlhDsaBuilder, PKeySlhDsaParams, Variant};
281+
282+
let key = PKeySlhDsaBuilder::<Private>::new_generate(Variant::SlhDsaShake128s)?
283+
.generate()?;
284+
let public_params = PKeySlhDsaParams::<Public>::from_pkey(&key)?;
285+
let secret_params = PKeySlhDsaParams::<Private>::from_pkey(&key)?;
286+
287+
let mut secret = Protected::from(vec![0; 64]);
288+
let mut public = [0; 32];
289+
debug_assert_eq!(secret.len(), secret_params.private_key_seed()?.len());
290+
debug_assert_eq!(public.len(), public_params.public_key()?.len());
291+
secret[..].copy_from_slice(secret_params.private_key_seed()?);
292+
public[..].copy_from_slice(public_params.public_key()?);
293+
294+
Ok((secret, public))
295+
}
296+
297+
fn slhdsa128s_sign(secret: &Protected, digest: &[u8])
298+
-> Result<Box<[u8; 7856]>>
299+
{
300+
use openssl::pkey_slh_dsa::{PKeySlhDsaBuilder, Variant};
301+
use openssl::signature::Signature;
302+
303+
let key = PKeySlhDsaBuilder::<Private>::new_private(
304+
Variant::SlhDsaShake128s, secret.as_ref())?
305+
.build()?;
306+
let mut algo = Signature::for_slh_dsa(Variant::SlhDsaShake128s)?;
307+
308+
let mut ctx = PkeyCtx::new(&key)?;
309+
ctx.sign_message_init(&mut algo)?;
310+
let mut signature: Box<[u8; 7856]> = vec![0; 7856].try_into().unwrap();
311+
let len = ctx.sign(digest, Some(&mut signature[..]))?;
312+
debug_assert_eq!(len, signature.len());
313+
314+
Ok(signature)
315+
}
316+
317+
fn slhdsa128s_verify(public: &[u8; 32], digest: &[u8], signature: &[u8; 7856])
318+
-> Result<bool>
319+
{
320+
use openssl::pkey_slh_dsa::{PKeySlhDsaBuilder, Variant};
321+
use openssl::signature::Signature;
322+
323+
let key = PKeySlhDsaBuilder::<Public>::new_public(
324+
Variant::SlhDsaShake128s, public)?
325+
.build()?;
326+
let mut algo = Signature::for_slh_dsa(Variant::SlhDsaShake128s)?;
327+
328+
let mut ctx = PkeyCtx::new(&key)?;
329+
ctx.verify_message_init(&mut algo)?;
330+
Ok(ctx.verify(digest, &signature[..])?)
331+
}
332+
333+
fn slhdsa128f_generate_key() -> Result<(Protected, [u8; 32])> {
334+
use openssl::pkey_slh_dsa::{PKeySlhDsaBuilder, PKeySlhDsaParams, Variant};
335+
336+
let key = PKeySlhDsaBuilder::<Private>::new_generate(Variant::SlhDsaShake128f)?
337+
.generate()?;
338+
let public_params = PKeySlhDsaParams::<Public>::from_pkey(&key)?;
339+
let secret_params = PKeySlhDsaParams::<Private>::from_pkey(&key)?;
340+
341+
let mut secret = Protected::from(vec![0; 64]);
342+
let mut public = [0; 32];
343+
debug_assert_eq!(secret.len(), secret_params.private_key_seed()?.len());
344+
debug_assert_eq!(public.len(), public_params.public_key()?.len());
345+
secret[..].copy_from_slice(secret_params.private_key_seed()?);
346+
public[..].copy_from_slice(public_params.public_key()?);
347+
348+
Ok((secret, public))
349+
}
350+
351+
fn slhdsa128f_sign(secret: &Protected, digest: &[u8])
352+
-> Result<Box<[u8; 17088]>>
353+
{
354+
use openssl::pkey_slh_dsa::{PKeySlhDsaBuilder, Variant};
355+
use openssl::signature::Signature;
356+
357+
let key = PKeySlhDsaBuilder::<Private>::new_private(
358+
Variant::SlhDsaShake128f, secret.as_ref())?
359+
.build()?;
360+
let mut algo = Signature::for_slh_dsa(Variant::SlhDsaShake128f)?;
361+
362+
let mut ctx = PkeyCtx::new(&key)?;
363+
ctx.sign_message_init(&mut algo)?;
364+
let mut signature: Box<[u8; 17088]> = vec![0; 17088].try_into().unwrap();
365+
let len = ctx.sign(digest, Some(&mut signature[..]))?;
366+
debug_assert_eq!(len, signature.len());
367+
368+
Ok(signature)
369+
}
370+
371+
fn slhdsa128f_verify(public: &[u8; 32], digest: &[u8], signature: &[u8; 17088])
372+
-> Result<bool>
373+
{
374+
use openssl::pkey_slh_dsa::{PKeySlhDsaBuilder, Variant};
375+
use openssl::signature::Signature;
376+
377+
let key = PKeySlhDsaBuilder::<Public>::new_public(
378+
Variant::SlhDsaShake128f, public)?
379+
.build()?;
380+
let mut algo = Signature::for_slh_dsa(Variant::SlhDsaShake128f)?;
381+
382+
let mut ctx = PkeyCtx::new(&key)?;
383+
ctx.verify_message_init(&mut algo)?;
384+
Ok(ctx.verify(digest, &signature[..])?)
385+
}
386+
387+
fn slhdsa256s_generate_key() -> Result<(Protected, Box<[u8; 64]>)> {
388+
use openssl::pkey_slh_dsa::{PKeySlhDsaBuilder, PKeySlhDsaParams, Variant};
389+
390+
let key = PKeySlhDsaBuilder::<Private>::new_generate(Variant::SlhDsaShake256s)?
391+
.generate()?;
392+
let public_params = PKeySlhDsaParams::<Public>::from_pkey(&key)?;
393+
let secret_params = PKeySlhDsaParams::<Private>::from_pkey(&key)?;
394+
395+
let mut secret = Protected::from(vec![0; 64]);
396+
let mut public = Box::new([0; 64]);
397+
debug_assert_eq!(secret.len(), secret_params.private_key_seed()?.len());
398+
debug_assert_eq!(public.len(), public_params.public_key()?.len());
399+
secret[..].copy_from_slice(secret_params.private_key_seed()?);
400+
public[..].copy_from_slice(public_params.public_key()?);
401+
402+
Ok((secret, public))
403+
}
404+
405+
fn slhdsa256s_sign(secret: &Protected, digest: &[u8])
406+
-> Result<Box<[u8; 29792]>>
407+
{
408+
use openssl::pkey_slh_dsa::{PKeySlhDsaBuilder, Variant};
409+
use openssl::signature::Signature;
410+
411+
let key = PKeySlhDsaBuilder::<Private>::new_private(
412+
Variant::SlhDsaShake256s, secret.as_ref())?
413+
.build()?;
414+
let mut algo = Signature::for_slh_dsa(Variant::SlhDsaShake256s)?;
415+
416+
let mut ctx = PkeyCtx::new(&key)?;
417+
ctx.sign_message_init(&mut algo)?;
418+
let mut signature: Box<[u8; 29792]> = vec![0; 29792].try_into().unwrap();
419+
let len = ctx.sign(digest, Some(&mut signature[..]))?;
420+
debug_assert_eq!(len, signature.len());
421+
422+
Ok(signature)
423+
}
424+
425+
fn slhdsa256s_verify(public: &[u8; 64], digest: &[u8], signature: &[u8; 29792])
426+
-> Result<bool>
427+
{
428+
use openssl::pkey_slh_dsa::{PKeySlhDsaBuilder, Variant};
429+
use openssl::signature::Signature;
430+
431+
let key = PKeySlhDsaBuilder::<Public>::new_public(
432+
Variant::SlhDsaShake256s, public)?
433+
.build()?;
434+
let mut algo = Signature::for_slh_dsa(Variant::SlhDsaShake256s)?;
435+
436+
let mut ctx = PkeyCtx::new(&key)?;
437+
ctx.verify_message_init(&mut algo)?;
438+
Ok(ctx.verify(digest, &signature[..])?)
439+
}
440+
278441
fn dsa_generate_key(p_bits: usize)
279442
-> Result<(MPI, MPI, MPI, MPI, ProtectedMPI)>
280443
{

0 commit comments

Comments
 (0)