1*e7be843bSPierre Pronchery#! /usr/bin/env perl 2*e7be843bSPierre Pronchery# Copyright 2022-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 Proncheryuse strict; 10*e7be843bSPierre Proncheryuse warnings; 11*e7be843bSPierre Pronchery 12*e7be843bSPierre Proncheryuse OpenSSL::Test::Utils; 13*e7be843bSPierre Proncheryuse File::Copy; 14*e7be843bSPierre Proncheryuse File::Compare qw(compare_text); 15*e7be843bSPierre Proncheryuse OpenSSL::Test qw/:DEFAULT srctop_file/; 16*e7be843bSPierre Pronchery 17*e7be843bSPierre Proncherysetup("test_pkey"); 18*e7be843bSPierre Pronchery 19*e7be843bSPierre Proncheryplan tests => 5; 20*e7be843bSPierre Pronchery 21*e7be843bSPierre Proncherymy @app = ('openssl', 'pkey'); 22*e7be843bSPierre Pronchery 23*e7be843bSPierre Proncherymy $in_key = srctop_file('test', 'certs', 'root-key.pem'); 24*e7be843bSPierre Proncherymy $pass = 'pass:password'; 25*e7be843bSPierre Pronchery 26*e7be843bSPierre Proncherysubtest "=== pkey typical en-/decryption (using AES256-CBC) ===" => sub { 27*e7be843bSPierre Pronchery plan tests => 4; 28*e7be843bSPierre Pronchery 29*e7be843bSPierre Pronchery my $encrypted_key = 'encrypted_key.pem'; 30*e7be843bSPierre Pronchery my $decrypted_key = 'decrypted_key.pem'; 31*e7be843bSPierre Pronchery 32*e7be843bSPierre Pronchery ok(run(app([@app, '-aes256', '-in', $in_key, '-out', $encrypted_key, 33*e7be843bSPierre Pronchery '-passout', $pass])), 34*e7be843bSPierre Pronchery "encrypt key (using aes-256-cbc)"); 35*e7be843bSPierre Pronchery 36*e7be843bSPierre Pronchery ok(run(app(['openssl', 'asn1parse', '-in', $encrypted_key, 37*e7be843bSPierre Pronchery '-offset', '34', '-length', '18'])), # incl. 2 bytes header 38*e7be843bSPierre Pronchery "encrypted key has default PBKDF2 PARAM 'salt length' 16"); 39*e7be843bSPierre Pronchery 40*e7be843bSPierre Pronchery ok(run(app([@app, '-in', $encrypted_key, '-out', $decrypted_key, 41*e7be843bSPierre Pronchery '-passin', $pass])), 42*e7be843bSPierre Pronchery "decrypt key"); 43*e7be843bSPierre Pronchery is(compare_text($in_key, $decrypted_key), 0, 44*e7be843bSPierre Pronchery "Same file contents after encrypting and decrypting in separate files"); 45*e7be843bSPierre Pronchery}; 46*e7be843bSPierre Pronchery 47*e7be843bSPierre Proncherysubtest "=== pkey handling of identical input and output files (using 3DES) and -traditional ===" => sub { 48*e7be843bSPierre Pronchery plan skip_all => "DES not supported in this build" if disabled("des"); 49*e7be843bSPierre Pronchery plan tests => 4; 50*e7be843bSPierre Pronchery 51*e7be843bSPierre Pronchery my $inout = 'inout.pem'; 52*e7be843bSPierre Pronchery 53*e7be843bSPierre Pronchery copy($in_key, $inout); 54*e7be843bSPierre Pronchery ok(run(app([@app, '-des3', '-traditional', '-in', $inout, '-out', $inout, 55*e7be843bSPierre Pronchery '-passout', $pass])), 56*e7be843bSPierre Pronchery "encrypt using identical infile and outfile"); 57*e7be843bSPierre Pronchery 58*e7be843bSPierre Pronchery sub file_line_contains { grep /$_[0]/, ((open F, $_[1]), <F>, close F) } 59*e7be843bSPierre Pronchery ok(file_line_contains("DEK-Info: DES-EDE3-CBC,", $inout), 60*e7be843bSPierre Pronchery "traditional encoding contains \"DEK-Info: DES-EDE3-CBC,\""); 61*e7be843bSPierre Pronchery 62*e7be843bSPierre Pronchery ok(run(app([@app, '-in', $inout, '-out', $inout, '-passin', $pass])), 63*e7be843bSPierre Pronchery "decrypt using identical infile and outfile"); 64*e7be843bSPierre Pronchery is(compare_text($in_key, $inout), 0, 65*e7be843bSPierre Pronchery "Same file contents after encrypting and decrypting using same file"); 66*e7be843bSPierre Pronchery}; 67*e7be843bSPierre Pronchery 68*e7be843bSPierre Proncherysubtest "=== pkey handling of public keys (Ed25519) ===" => sub { 69*e7be843bSPierre Pronchery plan skip_all => "ECX not supported inthis build" if disabled("ecx"); 70*e7be843bSPierre Pronchery plan tests => 6; 71*e7be843bSPierre Pronchery 72*e7be843bSPierre Pronchery my $in_ed_key = srctop_file('test', 'certs', 'root-ed25519.privkey.pem'); 73*e7be843bSPierre Pronchery my $in_pubkey = srctop_file('test', 'certs', 'root-ed25519.pubkey.pem'); 74*e7be843bSPierre Pronchery 75*e7be843bSPierre Pronchery my $pub_out1 = 'pub1.pem'; 76*e7be843bSPierre Pronchery ok(run(app([@app, '-in', $in_ed_key, '-pubout', '-out', $pub_out1])), 77*e7be843bSPierre Pronchery "extract public key"); 78*e7be843bSPierre Pronchery is(compare_text($in_pubkey, $pub_out1), 0, 79*e7be843bSPierre Pronchery "extracted public key is same as original public key"); 80*e7be843bSPierre Pronchery 81*e7be843bSPierre Pronchery my $pub_out2 = 'pub2.pem'; 82*e7be843bSPierre Pronchery ok(run(app([@app, '-in', $in_pubkey, '-pubin', '-pubout', '-out', $pub_out2])), 83*e7be843bSPierre Pronchery "read public key from pubfile"); 84*e7be843bSPierre Pronchery is(compare_text($in_pubkey, $pub_out2), 0, 85*e7be843bSPierre Pronchery "public key read using pubfile is same as original public key"); 86*e7be843bSPierre Pronchery 87*e7be843bSPierre Pronchery my $pub_out3 = 'pub3.pem'; 88*e7be843bSPierre Pronchery ok(run(app([@app, '-in', $in_ed_key, '-pubin', '-pubout', '-out', $pub_out3])), 89*e7be843bSPierre Pronchery "extract public key from pkey file with -pubin"); 90*e7be843bSPierre Pronchery is(compare_text($in_pubkey, $pub_out3), 0, 91*e7be843bSPierre Pronchery "public key extraced from pkey file with -pubin is same as original"); 92*e7be843bSPierre Pronchery}; 93*e7be843bSPierre Pronchery 94*e7be843bSPierre Pronchery 95*e7be843bSPierre Proncherysubtest "=== pkey handling of DER encoding ===" => sub { 96*e7be843bSPierre Pronchery plan tests => 4; 97*e7be843bSPierre Pronchery 98*e7be843bSPierre Pronchery my $der_out = 'key.der'; 99*e7be843bSPierre Pronchery my $pem_out = 'key.pem'; 100*e7be843bSPierre Pronchery ok(run(app([@app, '-in', $in_key, '-outform', 'DER', 101*e7be843bSPierre Pronchery '-out', $der_out])), 102*e7be843bSPierre Pronchery "write DER-encoded pkey"); 103*e7be843bSPierre Pronchery 104*e7be843bSPierre Pronchery ok(run(app(['openssl', 'asn1parse', '-in', $der_out, '-inform', 'DER', 105*e7be843bSPierre Pronchery '-offset', '268', '-length', '5'])), # incl. 2 bytes header 106*e7be843bSPierre Pronchery "see if length of the modulus encoding is included"); 107*e7be843bSPierre Pronchery 108*e7be843bSPierre Pronchery ok(run(app([@app, '-in', $der_out, '-inform', 'DER', 109*e7be843bSPierre Pronchery '-out', $pem_out])), 110*e7be843bSPierre Pronchery "read DER-encoded key"); 111*e7be843bSPierre Pronchery is(compare_text($in_key, $pem_out), 0, 112*e7be843bSPierre Pronchery "Same file contents after converting to DER and back"); 113*e7be843bSPierre Pronchery}; 114*e7be843bSPierre Pronchery 115*e7be843bSPierre Proncherysubtest "=== pkey text output ===" => sub { 116*e7be843bSPierre Pronchery plan tests => 3; 117*e7be843bSPierre Pronchery 118*e7be843bSPierre Pronchery ok((grep /BEGIN PRIVATE KEY/, 119*e7be843bSPierre Pronchery run(app([@app, '-in', $in_key, '-text']), capture => 1)), 120*e7be843bSPierre Pronchery "pkey text output contains PEM header"); 121*e7be843bSPierre Pronchery 122*e7be843bSPierre Pronchery ok(!(grep /BEGIN PRIVATE KEY/, 123*e7be843bSPierre Pronchery run(app([@app, '-in', $in_key, '-text', '-noout']), capture => 1)), 124*e7be843bSPierre Pronchery "pkey text output with -noout does not contain PEM header"); 125*e7be843bSPierre Pronchery 126*e7be843bSPierre Pronchery ok((grep /Private-Key:/, 127*e7be843bSPierre Pronchery run(app([@app, '-in', $in_key, '-text', '-noout']), capture => 1)), 128*e7be843bSPierre Pronchery "pkey text output (even with -noout) contains \"Private-Key:\""); 129*e7be843bSPierre Pronchery}; 130