mirror of
https://github.com/openssl/openssl.git
synced 2026-01-18 17:11:31 +01:00
Remove top-level engines dir.
Signed-off-by: Milan Broz <gmazyland@gmail.com> Reviewed-by: Neil Horman <nhorman@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/28548)
This commit is contained in:
@@ -1295,13 +1295,6 @@ errors:
|
||||
( b=`pwd`; set -e; cd $(SRCDIR); \
|
||||
$(PERL) util/ck_errf.pl -strict -internal; \
|
||||
$(PERL) -I$$b util/mkerr.pl $(ERROR_REBUILD) -internal )
|
||||
( b=`pwd`; set -e; cd $(SRCDIR)/engines; \
|
||||
for E in *.ec ; do \
|
||||
$(PERL) ../util/ck_errf.pl -strict \
|
||||
-conf $$E `basename $$E .ec`.c; \
|
||||
$(PERL) -I$$b ../util/mkerr.pl $(ERROR_REBUILD) -static \
|
||||
-conf $$E `basename $$E .ec`.c ; \
|
||||
done )
|
||||
|
||||
{- use File::Basename;
|
||||
|
||||
|
||||
@@ -1955,7 +1955,6 @@ foreach my $what (sort keys %disabled) {
|
||||
my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT";
|
||||
push @{$config{openssl_feature_defines}}, $macro;
|
||||
|
||||
$skipdir{engines} = $what if $what eq 'engine';
|
||||
$skipdir{"crypto/$skipdir"} = $what
|
||||
unless $what eq 'async' || $what eq 'err' || $what eq 'dso' || $what eq 'http';
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@ ENDIF
|
||||
IF[{- !$disabled{demos} -}]
|
||||
SUBDIRS=demos
|
||||
ENDIF
|
||||
IF[{- !$disabled{'deprecated-3.0'} -}]
|
||||
SUBDIRS=engines
|
||||
ENDIF
|
||||
SUBDIRS=exporters
|
||||
|
||||
LIBS=libcrypto libssl
|
||||
|
||||
@@ -1,628 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2011-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
|
||||
# ====================================================================
|
||||
# Written by Andy Polyakov, @dot-asm, initially for use in the OpenSSL
|
||||
# project. The module is, however, dual licensed under OpenSSL and
|
||||
# CRYPTOGAMS licenses depending on where you obtain it. For further
|
||||
# details see https://github.com/dot-asm/cryptogams/.
|
||||
# ====================================================================
|
||||
|
||||
# September 2011
|
||||
#
|
||||
# Assembler helpers for Padlock engine. Compared to original engine
|
||||
# version relying on inline assembler and compiled with gcc 3.4.6 it
|
||||
# was measured to provide ~100% improvement on misaligned data in ECB
|
||||
# mode and ~75% in CBC mode. For aligned data improvement can be
|
||||
# observed for short inputs only, e.g. 45% for 64-byte messages in
|
||||
# ECB mode, 20% in CBC. Difference in performance for aligned vs.
|
||||
# misaligned data depends on misalignment and is either ~1.8x or 2.9x.
|
||||
# These are approximately same factors as for hardware support, so
|
||||
# there is little reason to rely on the latter. On the contrary, it
|
||||
# might actually hurt performance in mixture of aligned and misaligned
|
||||
# buffers, because a) if you choose to flip 'align' flag in control
|
||||
# word on per-buffer basis, then you'd have to reload key context,
|
||||
# which incurs penalty; b) if you choose to set 'align' flag
|
||||
# permanently, it limits performance even for aligned data to ~1/2.
|
||||
# All above mentioned results were collected on 1.5GHz C7. Nano on the
|
||||
# other hand handles unaligned data more gracefully. Depending on
|
||||
# algorithm and how unaligned data is, hardware can be up to 70% more
|
||||
# efficient than below software alignment procedures, nor does 'align'
|
||||
# flag have affect on aligned performance [if has any meaning at all].
|
||||
# Therefore suggestion is to unconditionally set 'align' flag on Nano
|
||||
# for optimal performance.
|
||||
|
||||
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
push(@INC,"${dir}","${dir}../../crypto/perlasm");
|
||||
require "x86asm.pl";
|
||||
|
||||
$output=pop and open STDOUT,">$output";
|
||||
|
||||
&asm_init($ARGV[0]);
|
||||
|
||||
%PADLOCK_PREFETCH=(ecb=>128, cbc=>64); # prefetch errata
|
||||
$PADLOCK_CHUNK=512; # Must be a power of 2 larger than 16
|
||||
|
||||
$ctx="edx";
|
||||
$out="edi";
|
||||
$inp="esi";
|
||||
$len="ecx";
|
||||
$chunk="ebx";
|
||||
|
||||
&function_begin_B("padlock_capability");
|
||||
&push ("ebx");
|
||||
&pushf ();
|
||||
&pop ("eax");
|
||||
&mov ("ecx","eax");
|
||||
&xor ("eax",1<<21);
|
||||
&push ("eax");
|
||||
&popf ();
|
||||
&pushf ();
|
||||
&pop ("eax");
|
||||
&xor ("ecx","eax");
|
||||
&xor ("eax","eax");
|
||||
&bt ("ecx",21);
|
||||
&jnc (&label("noluck"));
|
||||
&cpuid ();
|
||||
&xor ("eax","eax");
|
||||
&cmp ("ebx","0x".unpack("H*",'tneC'));
|
||||
&jne (&label("zhaoxin"));
|
||||
&cmp ("edx","0x".unpack("H*",'Hrua'));
|
||||
&jne (&label("noluck"));
|
||||
&cmp ("ecx","0x".unpack("H*",'slua'));
|
||||
&jne (&label("noluck"));
|
||||
&jmp (&label("zhaoxinEnd"));
|
||||
&set_label("zhaoxin");
|
||||
&cmp ("ebx","0x".unpack("H*",'hS '));
|
||||
&jne (&label("noluck"));
|
||||
&cmp ("edx","0x".unpack("H*",'hgna'));
|
||||
&jne (&label("noluck"));
|
||||
&cmp ("ecx","0x".unpack("H*",' ia'));
|
||||
&jne (&label("noluck"));
|
||||
&set_label("zhaoxinEnd");
|
||||
&mov ("eax",0xC0000000);
|
||||
&cpuid ();
|
||||
&mov ("edx","eax");
|
||||
&xor ("eax","eax");
|
||||
&cmp ("edx",0xC0000001);
|
||||
&jb (&label("noluck"));
|
||||
&mov ("eax",1);
|
||||
&cpuid ();
|
||||
&or ("eax",0x0f);
|
||||
&xor ("ebx","ebx");
|
||||
&and ("eax",0x0fff);
|
||||
&cmp ("eax",0x06ff); # check for Nano
|
||||
&sete ("bl");
|
||||
&mov ("eax",0xC0000001);
|
||||
&push ("ebx");
|
||||
&cpuid ();
|
||||
&pop ("ebx");
|
||||
&mov ("eax","edx");
|
||||
&shl ("ebx",4); # bit#4 denotes Nano
|
||||
&and ("eax",0xffffffef);
|
||||
&or ("eax","ebx")
|
||||
&set_label("noluck");
|
||||
&pop ("ebx");
|
||||
&ret ();
|
||||
&function_end_B("padlock_capability")
|
||||
|
||||
&function_begin_B("padlock_key_bswap");
|
||||
&mov ("edx",&wparam(0));
|
||||
&mov ("ecx",&DWP(240,"edx"));
|
||||
&inc ("ecx");
|
||||
&shl ("ecx",2);
|
||||
&set_label("bswap_loop");
|
||||
&mov ("eax",&DWP(0,"edx"));
|
||||
&bswap ("eax");
|
||||
&mov (&DWP(0,"edx"),"eax");
|
||||
&lea ("edx",&DWP(4,"edx"));
|
||||
&sub ("ecx",1);
|
||||
&jnz (&label("bswap_loop"));
|
||||
&ret ();
|
||||
&function_end_B("padlock_key_bswap");
|
||||
|
||||
# This is heuristic key context tracing. At first one
|
||||
# believes that one should use atomic swap instructions,
|
||||
# but it's not actually necessary. Point is that if
|
||||
# padlock_saved_context was changed by another thread
|
||||
# after we've read it and before we compare it with ctx,
|
||||
# our key *shall* be reloaded upon thread context switch
|
||||
# and we are therefore set in either case...
|
||||
&static_label("padlock_saved_context");
|
||||
|
||||
&function_begin_B("padlock_verify_context");
|
||||
&mov ($ctx,&wparam(0));
|
||||
&lea ("eax",($::win32 or $::coff) ? &DWP(&label("padlock_saved_context")) :
|
||||
&DWP(&label("padlock_saved_context")."-".&label("verify_pic_point")));
|
||||
&pushf ();
|
||||
&call ("_padlock_verify_ctx");
|
||||
&set_label("verify_pic_point");
|
||||
&lea ("esp",&DWP(4,"esp"));
|
||||
&ret ();
|
||||
&function_end_B("padlock_verify_context");
|
||||
|
||||
&function_begin_B("_padlock_verify_ctx");
|
||||
&add ("eax",&DWP(0,"esp")) if(!($::win32 or $::coff));# &padlock_saved_context
|
||||
&bt (&DWP(4,"esp"),30); # eflags
|
||||
&jnc (&label("verified"));
|
||||
&cmp ($ctx,&DWP(0,"eax"));
|
||||
&je (&label("verified"));
|
||||
&pushf ();
|
||||
&popf ();
|
||||
&set_label("verified");
|
||||
&mov (&DWP(0,"eax"),$ctx);
|
||||
&ret ();
|
||||
&function_end_B("_padlock_verify_ctx");
|
||||
|
||||
&function_begin_B("padlock_reload_key");
|
||||
&pushf ();
|
||||
&popf ();
|
||||
&ret ();
|
||||
&function_end_B("padlock_reload_key");
|
||||
|
||||
&function_begin_B("padlock_aes_block");
|
||||
&push ("edi");
|
||||
&push ("esi");
|
||||
&push ("ebx");
|
||||
&mov ($out,&wparam(0)); # must be 16-byte aligned
|
||||
&mov ($inp,&wparam(1)); # must be 16-byte aligned
|
||||
&mov ($ctx,&wparam(2));
|
||||
&mov ($len,1);
|
||||
&lea ("ebx",&DWP(32,$ctx)); # key
|
||||
&lea ($ctx,&DWP(16,$ctx)); # control word
|
||||
&data_byte(0xf3,0x0f,0xa7,0xc8); # rep xcryptecb
|
||||
&pop ("ebx");
|
||||
&pop ("esi");
|
||||
&pop ("edi");
|
||||
&ret ();
|
||||
&function_end_B("padlock_aes_block");
|
||||
|
||||
sub generate_mode {
|
||||
my ($mode,$opcode) = @_;
|
||||
# int padlock_$mode_encrypt(void *out, const void *inp,
|
||||
# struct padlock_cipher_data *ctx, size_t len);
|
||||
&function_begin("padlock_${mode}_encrypt");
|
||||
&mov ($out,&wparam(0));
|
||||
&mov ($inp,&wparam(1));
|
||||
&mov ($ctx,&wparam(2));
|
||||
&mov ($len,&wparam(3));
|
||||
&test ($ctx,15);
|
||||
&jnz (&label("${mode}_abort"));
|
||||
&test ($len,15);
|
||||
&jnz (&label("${mode}_abort"));
|
||||
&lea ("eax",($::win32 or $::coff) ? &DWP(&label("padlock_saved_context")) :
|
||||
&DWP(&label("padlock_saved_context")."-".&label("${mode}_pic_point")));
|
||||
&pushf ();
|
||||
&cld ();
|
||||
&call ("_padlock_verify_ctx");
|
||||
&set_label("${mode}_pic_point");
|
||||
&lea ($ctx,&DWP(16,$ctx)); # control word
|
||||
&xor ("eax","eax");
|
||||
if ($mode eq "ctr32") {
|
||||
&movq ("mm0",&QWP(-16,$ctx)); # load [upper part of] counter
|
||||
} else {
|
||||
&xor ("ebx","ebx");
|
||||
&test (&DWP(0,$ctx),1<<5); # align bit in control word
|
||||
&jnz (&label("${mode}_aligned"));
|
||||
&test ($out,0x0f);
|
||||
&setz ("al"); # !out_misaligned
|
||||
&test ($inp,0x0f);
|
||||
&setz ("bl"); # !inp_misaligned
|
||||
&test ("eax","ebx");
|
||||
&jnz (&label("${mode}_aligned"));
|
||||
&neg ("eax");
|
||||
}
|
||||
&mov ($chunk,$PADLOCK_CHUNK);
|
||||
¬ ("eax"); # out_misaligned?-1:0
|
||||
&lea ("ebp",&DWP(-24,"esp"));
|
||||
&cmp ($len,$chunk);
|
||||
&cmovc ($chunk,$len); # chunk=len>PADLOCK_CHUNK?PADLOCK_CHUNK:len
|
||||
&and ("eax",$chunk); # out_misaligned?chunk:0
|
||||
&mov ($chunk,$len);
|
||||
&neg ("eax");
|
||||
&and ($chunk,$PADLOCK_CHUNK-1); # chunk=len%PADLOCK_CHUNK
|
||||
&lea ("esp",&DWP(0,"eax","ebp")); # alloca
|
||||
&mov ("eax",$PADLOCK_CHUNK);
|
||||
&cmovz ($chunk,"eax"); # chunk=chunk?:PADLOCK_CHUNK
|
||||
&mov ("eax","ebp");
|
||||
&and ("ebp",-16);
|
||||
&and ("esp",-16);
|
||||
&mov (&DWP(16,"ebp"),"eax");
|
||||
if ($PADLOCK_PREFETCH{$mode}) {
|
||||
&cmp ($len,$chunk);
|
||||
&ja (&label("${mode}_loop"));
|
||||
&mov ("eax",$inp); # check if prefetch crosses page
|
||||
&cmp ("ebp","esp");
|
||||
&cmove ("eax",$out);
|
||||
&add ("eax",$len);
|
||||
&neg ("eax");
|
||||
&and ("eax",0xfff); # distance to page boundary
|
||||
&cmp ("eax",$PADLOCK_PREFETCH{$mode});
|
||||
&mov ("eax",-$PADLOCK_PREFETCH{$mode});
|
||||
&cmovae ("eax",$chunk); # mask=distance<prefetch?-prefetch:-1
|
||||
&and ($chunk,"eax");
|
||||
&jz (&label("${mode}_unaligned_tail"));
|
||||
}
|
||||
&jmp (&label("${mode}_loop"));
|
||||
|
||||
&set_label("${mode}_loop",16);
|
||||
&mov (&DWP(0,"ebp"),$out); # save parameters
|
||||
&mov (&DWP(4,"ebp"),$inp);
|
||||
&mov (&DWP(8,"ebp"),$len);
|
||||
&mov ($len,$chunk);
|
||||
&mov (&DWP(12,"ebp"),$chunk); # chunk
|
||||
if ($mode eq "ctr32") {
|
||||
&mov ("ecx",&DWP(-4,$ctx));
|
||||
&xor ($out,$out);
|
||||
&mov ("eax",&DWP(-8,$ctx)); # borrow $len
|
||||
&set_label("${mode}_prepare");
|
||||
&mov (&DWP(12,"esp",$out),"ecx");
|
||||
&bswap ("ecx");
|
||||
&movq (&QWP(0,"esp",$out),"mm0");
|
||||
&inc ("ecx");
|
||||
&mov (&DWP(8,"esp",$out),"eax");
|
||||
&bswap ("ecx");
|
||||
&lea ($out,&DWP(16,$out));
|
||||
&cmp ($out,$chunk);
|
||||
&jb (&label("${mode}_prepare"));
|
||||
|
||||
&mov (&DWP(-4,$ctx),"ecx");
|
||||
&lea ($inp,&DWP(0,"esp"));
|
||||
&lea ($out,&DWP(0,"esp"));
|
||||
&mov ($len,$chunk);
|
||||
} else {
|
||||
&test ($out,0x0f); # out_misaligned
|
||||
&cmovnz ($out,"esp");
|
||||
&test ($inp,0x0f); # inp_misaligned
|
||||
&jz (&label("${mode}_inp_aligned"));
|
||||
&shr ($len,2);
|
||||
&data_byte(0xf3,0xa5); # rep movsl
|
||||
&sub ($out,$chunk);
|
||||
&mov ($len,$chunk);
|
||||
&mov ($inp,$out);
|
||||
&set_label("${mode}_inp_aligned");
|
||||
}
|
||||
&lea ("eax",&DWP(-16,$ctx)); # ivp
|
||||
&lea ("ebx",&DWP(16,$ctx)); # key
|
||||
&shr ($len,4); # len/=AES_BLOCK_SIZE
|
||||
&data_byte(0xf3,0x0f,0xa7,$opcode); # rep xcrypt*
|
||||
if ($mode !~ /ecb|ctr/) {
|
||||
&movaps ("xmm0",&QWP(0,"eax"));
|
||||
&movaps (&QWP(-16,$ctx),"xmm0"); # copy [or refresh] iv
|
||||
}
|
||||
&mov ($out,&DWP(0,"ebp")); # restore parameters
|
||||
&mov ($chunk,&DWP(12,"ebp"));
|
||||
if ($mode eq "ctr32") {
|
||||
&mov ($inp,&DWP(4,"ebp"));
|
||||
&xor ($len,$len);
|
||||
&set_label("${mode}_xor");
|
||||
&movups ("xmm1",&QWP(0,$inp,$len));
|
||||
&lea ($len,&DWP(16,$len));
|
||||
&pxor ("xmm1",&QWP(-16,"esp",$len));
|
||||
&movups (&QWP(-16,$out,$len),"xmm1");
|
||||
&cmp ($len,$chunk);
|
||||
&jb (&label("${mode}_xor"));
|
||||
} else {
|
||||
&test ($out,0x0f);
|
||||
&jz (&label("${mode}_out_aligned"));
|
||||
&mov ($len,$chunk);
|
||||
&lea ($inp,&DWP(0,"esp"));
|
||||
&shr ($len,2);
|
||||
&data_byte(0xf3,0xa5); # rep movsl
|
||||
&sub ($out,$chunk);
|
||||
&set_label("${mode}_out_aligned");
|
||||
&mov ($inp,&DWP(4,"ebp"));
|
||||
}
|
||||
&mov ($len,&DWP(8,"ebp"));
|
||||
&add ($out,$chunk);
|
||||
&add ($inp,$chunk);
|
||||
&sub ($len,$chunk);
|
||||
&mov ($chunk,$PADLOCK_CHUNK);
|
||||
if (!$PADLOCK_PREFETCH{$mode}) {
|
||||
&jnz (&label("${mode}_loop"));
|
||||
} else {
|
||||
&jz (&label("${mode}_break"));
|
||||
&cmp ($len,$chunk);
|
||||
&jae (&label("${mode}_loop"));
|
||||
|
||||
&set_label("${mode}_unaligned_tail");
|
||||
&xor ("eax","eax");
|
||||
&cmp ("esp","ebp");
|
||||
&cmove ("eax",$len);
|
||||
&sub ("esp","eax"); # alloca
|
||||
&mov ("eax", $out); # save parameters
|
||||
&mov ($chunk,$len);
|
||||
&shr ($len,2);
|
||||
&lea ($out,&DWP(0,"esp"));
|
||||
&data_byte(0xf3,0xa5); # rep movsl
|
||||
&mov ($inp,"esp");
|
||||
&mov ($out,"eax"); # restore parameters
|
||||
&mov ($len,$chunk);
|
||||
&jmp (&label("${mode}_loop"));
|
||||
|
||||
&set_label("${mode}_break",16);
|
||||
}
|
||||
if ($mode ne "ctr32") {
|
||||
&cmp ("esp","ebp");
|
||||
&je (&label("${mode}_done"));
|
||||
}
|
||||
&pxor ("xmm0","xmm0");
|
||||
&lea ("eax",&DWP(0,"esp"));
|
||||
&set_label("${mode}_bzero");
|
||||
&movaps (&QWP(0,"eax"),"xmm0");
|
||||
&lea ("eax",&DWP(16,"eax"));
|
||||
&cmp ("ebp","eax");
|
||||
&ja (&label("${mode}_bzero"));
|
||||
|
||||
&set_label("${mode}_done");
|
||||
&mov ("ebp",&DWP(16,"ebp"));
|
||||
&lea ("esp",&DWP(24,"ebp"));
|
||||
if ($mode ne "ctr32") {
|
||||
&jmp (&label("${mode}_exit"));
|
||||
|
||||
&set_label("${mode}_aligned",16);
|
||||
if ($PADLOCK_PREFETCH{$mode}) {
|
||||
&lea ("ebp",&DWP(0,$inp,$len));
|
||||
&neg ("ebp");
|
||||
&and ("ebp",0xfff); # distance to page boundary
|
||||
&xor ("eax","eax");
|
||||
&cmp ("ebp",$PADLOCK_PREFETCH{$mode});
|
||||
&mov ("ebp",$PADLOCK_PREFETCH{$mode}-1);
|
||||
&cmovae ("ebp","eax");
|
||||
&and ("ebp",$len); # remainder
|
||||
&sub ($len,"ebp");
|
||||
&jz (&label("${mode}_aligned_tail"));
|
||||
}
|
||||
&lea ("eax",&DWP(-16,$ctx)); # ivp
|
||||
&lea ("ebx",&DWP(16,$ctx)); # key
|
||||
&shr ($len,4); # len/=AES_BLOCK_SIZE
|
||||
&data_byte(0xf3,0x0f,0xa7,$opcode); # rep xcrypt*
|
||||
if ($mode ne "ecb") {
|
||||
&movaps ("xmm0",&QWP(0,"eax"));
|
||||
&movaps (&QWP(-16,$ctx),"xmm0"); # copy [or refresh] iv
|
||||
}
|
||||
if ($PADLOCK_PREFETCH{$mode}) {
|
||||
&test ("ebp","ebp");
|
||||
&jz (&label("${mode}_exit"));
|
||||
|
||||
&set_label("${mode}_aligned_tail");
|
||||
&mov ($len,"ebp");
|
||||
&lea ("ebp",&DWP(-24,"esp"));
|
||||
&mov ("esp","ebp");
|
||||
&mov ("eax","ebp");
|
||||
&sub ("esp",$len);
|
||||
&and ("ebp",-16);
|
||||
&and ("esp",-16);
|
||||
&mov (&DWP(16,"ebp"),"eax");
|
||||
&mov ("eax", $out); # save parameters
|
||||
&mov ($chunk,$len);
|
||||
&shr ($len,2);
|
||||
&lea ($out,&DWP(0,"esp"));
|
||||
&data_byte(0xf3,0xa5); # rep movsl
|
||||
&mov ($inp,"esp");
|
||||
&mov ($out,"eax"); # restore parameters
|
||||
&mov ($len,$chunk);
|
||||
&jmp (&label("${mode}_loop"));
|
||||
}
|
||||
&set_label("${mode}_exit"); }
|
||||
&mov ("eax",1);
|
||||
&lea ("esp",&DWP(4,"esp")); # popf
|
||||
&emms () if ($mode eq "ctr32");
|
||||
&set_label("${mode}_abort");
|
||||
&function_end("padlock_${mode}_encrypt");
|
||||
}
|
||||
|
||||
&generate_mode("ecb",0xc8);
|
||||
&generate_mode("cbc",0xd0);
|
||||
&generate_mode("cfb",0xe0);
|
||||
&generate_mode("ofb",0xe8);
|
||||
&generate_mode("ctr32",0xc8); # yes, it implements own CTR with ECB opcode,
|
||||
# because hardware CTR was introduced later
|
||||
# and even has errata on certain C7 stepping.
|
||||
# own implementation *always* works, though
|
||||
# ~15% slower than dedicated hardware...
|
||||
|
||||
&function_begin_B("padlock_xstore");
|
||||
&push ("edi");
|
||||
&mov ("edi",&wparam(0));
|
||||
&mov ("edx",&wparam(1));
|
||||
&data_byte(0x0f,0xa7,0xc0); # xstore
|
||||
&pop ("edi");
|
||||
&ret ();
|
||||
&function_end_B("padlock_xstore");
|
||||
|
||||
&function_begin_B("_win32_segv_handler");
|
||||
&mov ("eax",1); # ExceptionContinueSearch
|
||||
&mov ("edx",&wparam(0)); # *ExceptionRecord
|
||||
&mov ("ecx",&wparam(2)); # *ContextRecord
|
||||
&cmp (&DWP(0,"edx"),0xC0000005) # ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION
|
||||
&jne (&label("ret"));
|
||||
&add (&DWP(184,"ecx"),4); # skip over rep sha*
|
||||
&mov ("eax",0); # ExceptionContinueExecution
|
||||
&set_label("ret");
|
||||
&ret ();
|
||||
&function_end_B("_win32_segv_handler");
|
||||
&safeseh("_win32_segv_handler") if ($::win32);
|
||||
|
||||
&function_begin_B("padlock_sha1_oneshot");
|
||||
&push ("edi");
|
||||
&push ("esi");
|
||||
&xor ("eax","eax");
|
||||
&mov ("edi",&wparam(0));
|
||||
&mov ("esi",&wparam(1));
|
||||
&mov ("ecx",&wparam(2));
|
||||
if ($::win32 or $::coff) {
|
||||
&push (&::islabel("_win32_segv_handler"));
|
||||
&data_byte(0x64,0xff,0x30); # push %fs:(%eax)
|
||||
&data_byte(0x64,0x89,0x20); # mov %esp,%fs:(%eax)
|
||||
}
|
||||
&mov ("edx","esp"); # put aside %esp
|
||||
&add ("esp",-128); # 32 is enough but spec says 128
|
||||
&movups ("xmm0",&QWP(0,"edi")); # copy-in context
|
||||
&and ("esp",-16);
|
||||
&mov ("eax",&DWP(16,"edi"));
|
||||
&movaps (&QWP(0,"esp"),"xmm0");
|
||||
&mov ("edi","esp");
|
||||
&mov (&DWP(16,"esp"),"eax");
|
||||
&xor ("eax","eax");
|
||||
&data_byte(0xf3,0x0f,0xa6,0xc8); # rep xsha1
|
||||
&movaps ("xmm0",&QWP(0,"esp"));
|
||||
&mov ("eax",&DWP(16,"esp"));
|
||||
&mov ("esp","edx"); # restore %esp
|
||||
if ($::win32 or $::coff) {
|
||||
&data_byte(0x64,0x8f,0x05,0,0,0,0); # pop %fs:0
|
||||
&lea ("esp",&DWP(4,"esp"));
|
||||
}
|
||||
&mov ("edi",&wparam(0));
|
||||
&movups (&QWP(0,"edi"),"xmm0"); # copy-out context
|
||||
&mov (&DWP(16,"edi"),"eax");
|
||||
&pop ("esi");
|
||||
&pop ("edi");
|
||||
&ret ();
|
||||
&function_end_B("padlock_sha1_oneshot");
|
||||
|
||||
&function_begin_B("padlock_sha1_blocks");
|
||||
&push ("edi");
|
||||
&push ("esi");
|
||||
&mov ("edi",&wparam(0));
|
||||
&mov ("esi",&wparam(1));
|
||||
&mov ("edx","esp"); # put aside %esp
|
||||
&mov ("ecx",&wparam(2));
|
||||
&add ("esp",-128);
|
||||
&movups ("xmm0",&QWP(0,"edi")); # copy-in context
|
||||
&and ("esp",-16);
|
||||
&mov ("eax",&DWP(16,"edi"));
|
||||
&movaps (&QWP(0,"esp"),"xmm0");
|
||||
&mov ("edi","esp");
|
||||
&mov (&DWP(16,"esp"),"eax");
|
||||
&mov ("eax",-1);
|
||||
&data_byte(0xf3,0x0f,0xa6,0xc8); # rep xsha1
|
||||
&movaps ("xmm0",&QWP(0,"esp"));
|
||||
&mov ("eax",&DWP(16,"esp"));
|
||||
&mov ("esp","edx"); # restore %esp
|
||||
&mov ("edi",&wparam(0));
|
||||
&movups (&QWP(0,"edi"),"xmm0"); # copy-out context
|
||||
&mov (&DWP(16,"edi"),"eax");
|
||||
&pop ("esi");
|
||||
&pop ("edi");
|
||||
&ret ();
|
||||
&function_end_B("padlock_sha1_blocks");
|
||||
|
||||
&function_begin_B("padlock_sha256_oneshot");
|
||||
&push ("edi");
|
||||
&push ("esi");
|
||||
&xor ("eax","eax");
|
||||
&mov ("edi",&wparam(0));
|
||||
&mov ("esi",&wparam(1));
|
||||
&mov ("ecx",&wparam(2));
|
||||
if ($::win32 or $::coff) {
|
||||
&push (&::islabel("_win32_segv_handler"));
|
||||
&data_byte(0x64,0xff,0x30); # push %fs:(%eax)
|
||||
&data_byte(0x64,0x89,0x20); # mov %esp,%fs:(%eax)
|
||||
}
|
||||
&mov ("edx","esp"); # put aside %esp
|
||||
&add ("esp",-128);
|
||||
&movups ("xmm0",&QWP(0,"edi")); # copy-in context
|
||||
&and ("esp",-16);
|
||||
&movups ("xmm1",&QWP(16,"edi"));
|
||||
&movaps (&QWP(0,"esp"),"xmm0");
|
||||
&mov ("edi","esp");
|
||||
&movaps (&QWP(16,"esp"),"xmm1");
|
||||
&xor ("eax","eax");
|
||||
&data_byte(0xf3,0x0f,0xa6,0xd0); # rep xsha256
|
||||
&movaps ("xmm0",&QWP(0,"esp"));
|
||||
&movaps ("xmm1",&QWP(16,"esp"));
|
||||
&mov ("esp","edx"); # restore %esp
|
||||
if ($::win32 or $::coff) {
|
||||
&data_byte(0x64,0x8f,0x05,0,0,0,0); # pop %fs:0
|
||||
&lea ("esp",&DWP(4,"esp"));
|
||||
}
|
||||
&mov ("edi",&wparam(0));
|
||||
&movups (&QWP(0,"edi"),"xmm0"); # copy-out context
|
||||
&movups (&QWP(16,"edi"),"xmm1");
|
||||
&pop ("esi");
|
||||
&pop ("edi");
|
||||
&ret ();
|
||||
&function_end_B("padlock_sha256_oneshot");
|
||||
|
||||
&function_begin_B("padlock_sha256_blocks");
|
||||
&push ("edi");
|
||||
&push ("esi");
|
||||
&mov ("edi",&wparam(0));
|
||||
&mov ("esi",&wparam(1));
|
||||
&mov ("ecx",&wparam(2));
|
||||
&mov ("edx","esp"); # put aside %esp
|
||||
&add ("esp",-128);
|
||||
&movups ("xmm0",&QWP(0,"edi")); # copy-in context
|
||||
&and ("esp",-16);
|
||||
&movups ("xmm1",&QWP(16,"edi"));
|
||||
&movaps (&QWP(0,"esp"),"xmm0");
|
||||
&mov ("edi","esp");
|
||||
&movaps (&QWP(16,"esp"),"xmm1");
|
||||
&mov ("eax",-1);
|
||||
&data_byte(0xf3,0x0f,0xa6,0xd0); # rep xsha256
|
||||
&movaps ("xmm0",&QWP(0,"esp"));
|
||||
&movaps ("xmm1",&QWP(16,"esp"));
|
||||
&mov ("esp","edx"); # restore %esp
|
||||
&mov ("edi",&wparam(0));
|
||||
&movups (&QWP(0,"edi"),"xmm0"); # copy-out context
|
||||
&movups (&QWP(16,"edi"),"xmm1");
|
||||
&pop ("esi");
|
||||
&pop ("edi");
|
||||
&ret ();
|
||||
&function_end_B("padlock_sha256_blocks");
|
||||
|
||||
&function_begin_B("padlock_sha512_blocks");
|
||||
&push ("edi");
|
||||
&push ("esi");
|
||||
&mov ("edi",&wparam(0));
|
||||
&mov ("esi",&wparam(1));
|
||||
&mov ("ecx",&wparam(2));
|
||||
&mov ("edx","esp"); # put aside %esp
|
||||
&add ("esp",-128);
|
||||
&movups ("xmm0",&QWP(0,"edi")); # copy-in context
|
||||
&and ("esp",-16);
|
||||
&movups ("xmm1",&QWP(16,"edi"));
|
||||
&movups ("xmm2",&QWP(32,"edi"));
|
||||
&movups ("xmm3",&QWP(48,"edi"));
|
||||
&movaps (&QWP(0,"esp"),"xmm0");
|
||||
&mov ("edi","esp");
|
||||
&movaps (&QWP(16,"esp"),"xmm1");
|
||||
&movaps (&QWP(32,"esp"),"xmm2");
|
||||
&movaps (&QWP(48,"esp"),"xmm3");
|
||||
&data_byte(0xf3,0x0f,0xa6,0xe0); # rep xsha512
|
||||
&movaps ("xmm0",&QWP(0,"esp"));
|
||||
&movaps ("xmm1",&QWP(16,"esp"));
|
||||
&movaps ("xmm2",&QWP(32,"esp"));
|
||||
&movaps ("xmm3",&QWP(48,"esp"));
|
||||
&mov ("esp","edx"); # restore %esp
|
||||
&mov ("edi",&wparam(0));
|
||||
&movups (&QWP(0,"edi"),"xmm0"); # copy-out context
|
||||
&movups (&QWP(16,"edi"),"xmm1");
|
||||
&movups (&QWP(32,"edi"),"xmm2");
|
||||
&movups (&QWP(48,"edi"),"xmm3");
|
||||
&pop ("esi");
|
||||
&pop ("edi");
|
||||
&ret ();
|
||||
&function_end_B("padlock_sha512_blocks");
|
||||
|
||||
&asciz ("VIA Padlock x86 module, CRYPTOGAMS by <https://github.com/dot-asm>");
|
||||
&align (16);
|
||||
|
||||
&dataseg();
|
||||
# Essentially this variable belongs in thread local storage.
|
||||
# Having this variable global on the other hand can only cause
|
||||
# few bogus key reloads [if any at all on signle-CPU system],
|
||||
# so we accept the penalty...
|
||||
&set_label("padlock_saved_context",4);
|
||||
&data_word(0);
|
||||
|
||||
&asm_finish();
|
||||
|
||||
close STDOUT;
|
||||
@@ -1,587 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2011-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
|
||||
# ====================================================================
|
||||
# Written by Andy Polyakov, @dot-asm, initially for use in the OpenSSL
|
||||
# project. The module is, however, dual licensed under OpenSSL and
|
||||
# CRYPTOGAMS licenses depending on where you obtain it. For further
|
||||
# details see https://github.com/dot-asm/cryptogams/.
|
||||
# ====================================================================
|
||||
|
||||
# September 2011
|
||||
#
|
||||
# Assembler helpers for Padlock engine. See even e_padlock-x86.pl for
|
||||
# details.
|
||||
|
||||
# $output is the last argument if it looks like a file (it has an extension)
|
||||
# $flavour is the first argument if it doesn't look like a file
|
||||
$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
|
||||
$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
|
||||
|
||||
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
|
||||
|
||||
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
|
||||
( $xlate="${dir}../../crypto/perlasm/x86_64-xlate.pl" and -f $xlate) or
|
||||
die "can't locate x86_64-xlate.pl";
|
||||
|
||||
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
|
||||
or die "can't call $xlate: $!";
|
||||
*STDOUT=*OUT;
|
||||
|
||||
$code=".text\n";
|
||||
|
||||
%PADLOCK_PREFETCH=(ecb=>128, cbc=>64, ctr32=>32); # prefetch errata
|
||||
$PADLOCK_CHUNK=512; # Must be a power of 2 between 32 and 2^20
|
||||
|
||||
$ctx="%rdx";
|
||||
$out="%rdi";
|
||||
$inp="%rsi";
|
||||
$len="%rcx";
|
||||
$chunk="%rbx";
|
||||
|
||||
($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
|
||||
("%rdi","%rsi","%rdx","%rcx"); # Unix order
|
||||
|
||||
$code.=<<___;
|
||||
.globl padlock_capability
|
||||
.type padlock_capability,\@abi-omnipotent
|
||||
.align 16
|
||||
padlock_capability:
|
||||
mov %rbx,%r8
|
||||
xor %eax,%eax
|
||||
cpuid
|
||||
xor %eax,%eax
|
||||
cmp \$`"0x".unpack("H*",'tneC')`,%ebx
|
||||
jne .Lzhaoxin
|
||||
cmp \$`"0x".unpack("H*",'Hrua')`,%edx
|
||||
jne .Lnoluck
|
||||
cmp \$`"0x".unpack("H*",'slua')`,%ecx
|
||||
jne .Lnoluck
|
||||
jmp .LzhaoxinEnd
|
||||
.Lzhaoxin:
|
||||
cmp \$`"0x".unpack("H*",'hS ')`,%ebx
|
||||
jne .Lnoluck
|
||||
cmp \$`"0x".unpack("H*",'hgna')`,%edx
|
||||
jne .Lnoluck
|
||||
cmp \$`"0x".unpack("H*",' ia')`,%ecx
|
||||
jne .Lnoluck
|
||||
.LzhaoxinEnd:
|
||||
mov \$0xC0000000,%eax
|
||||
cpuid
|
||||
mov %eax,%edx
|
||||
xor %eax,%eax
|
||||
cmp \$0xC0000001,%edx
|
||||
jb .Lnoluck
|
||||
mov \$0xC0000001,%eax
|
||||
cpuid
|
||||
mov %edx,%eax
|
||||
and \$0xffffffef,%eax
|
||||
or \$0x10,%eax # set Nano bit#4
|
||||
.Lnoluck:
|
||||
mov %r8,%rbx
|
||||
ret
|
||||
.size padlock_capability,.-padlock_capability
|
||||
|
||||
.globl padlock_key_bswap
|
||||
.type padlock_key_bswap,\@abi-omnipotent,0
|
||||
.align 16
|
||||
padlock_key_bswap:
|
||||
mov 240($arg1),%edx
|
||||
inc %edx
|
||||
shl \$2,%edx
|
||||
.Lbswap_loop:
|
||||
mov ($arg1),%eax
|
||||
bswap %eax
|
||||
mov %eax,($arg1)
|
||||
lea 4($arg1),$arg1
|
||||
sub \$1,%edx
|
||||
jnz .Lbswap_loop
|
||||
ret
|
||||
.size padlock_key_bswap,.-padlock_key_bswap
|
||||
|
||||
.globl padlock_verify_context
|
||||
.type padlock_verify_context,\@abi-omnipotent
|
||||
.align 16
|
||||
padlock_verify_context:
|
||||
mov $arg1,$ctx
|
||||
pushf
|
||||
lea .Lpadlock_saved_context(%rip),%rax
|
||||
call _padlock_verify_ctx
|
||||
lea 8(%rsp),%rsp
|
||||
ret
|
||||
.size padlock_verify_context,.-padlock_verify_context
|
||||
|
||||
.type _padlock_verify_ctx,\@abi-omnipotent
|
||||
.align 16
|
||||
_padlock_verify_ctx:
|
||||
mov 8(%rsp),%r8
|
||||
bt \$30,%r8
|
||||
jnc .Lverified
|
||||
cmp (%rax),$ctx
|
||||
je .Lverified
|
||||
pushf
|
||||
popf
|
||||
.Lverified:
|
||||
mov $ctx,(%rax)
|
||||
ret
|
||||
.size _padlock_verify_ctx,.-_padlock_verify_ctx
|
||||
|
||||
.globl padlock_reload_key
|
||||
.type padlock_reload_key,\@abi-omnipotent
|
||||
.align 16
|
||||
padlock_reload_key:
|
||||
pushf
|
||||
popf
|
||||
ret
|
||||
.size padlock_reload_key,.-padlock_reload_key
|
||||
|
||||
.globl padlock_aes_block
|
||||
.type padlock_aes_block,\@function,3
|
||||
.align 16
|
||||
padlock_aes_block:
|
||||
mov %rbx,%r8
|
||||
mov \$1,$len
|
||||
lea 32($ctx),%rbx # key
|
||||
lea 16($ctx),$ctx # control word
|
||||
.byte 0xf3,0x0f,0xa7,0xc8 # rep xcryptecb
|
||||
mov %r8,%rbx
|
||||
ret
|
||||
.size padlock_aes_block,.-padlock_aes_block
|
||||
|
||||
.globl padlock_xstore
|
||||
.type padlock_xstore,\@function,2
|
||||
.align 16
|
||||
padlock_xstore:
|
||||
mov %esi,%edx
|
||||
.byte 0x0f,0xa7,0xc0 # xstore
|
||||
ret
|
||||
.size padlock_xstore,.-padlock_xstore
|
||||
|
||||
.globl padlock_sha1_oneshot
|
||||
.type padlock_sha1_oneshot,\@function,3
|
||||
.align 16
|
||||
padlock_sha1_oneshot:
|
||||
mov %rdx,%rcx
|
||||
mov %rdi,%rdx # put aside %rdi
|
||||
movups (%rdi),%xmm0 # copy-in context
|
||||
sub \$128+8,%rsp
|
||||
mov 16(%rdi),%eax
|
||||
movaps %xmm0,(%rsp)
|
||||
mov %rsp,%rdi
|
||||
mov %eax,16(%rsp)
|
||||
xor %rax,%rax
|
||||
.byte 0xf3,0x0f,0xa6,0xc8 # rep xsha1
|
||||
movaps (%rsp),%xmm0
|
||||
mov 16(%rsp),%eax
|
||||
add \$128+8,%rsp
|
||||
movups %xmm0,(%rdx) # copy-out context
|
||||
mov %eax,16(%rdx)
|
||||
ret
|
||||
.size padlock_sha1_oneshot,.-padlock_sha1_oneshot
|
||||
|
||||
.globl padlock_sha1_blocks
|
||||
.type padlock_sha1_blocks,\@function,3
|
||||
.align 16
|
||||
padlock_sha1_blocks:
|
||||
mov %rdx,%rcx
|
||||
mov %rdi,%rdx # put aside %rdi
|
||||
movups (%rdi),%xmm0 # copy-in context
|
||||
sub \$128+8,%rsp
|
||||
mov 16(%rdi),%eax
|
||||
movaps %xmm0,(%rsp)
|
||||
mov %rsp,%rdi
|
||||
mov %eax,16(%rsp)
|
||||
mov \$-1,%rax
|
||||
.byte 0xf3,0x0f,0xa6,0xc8 # rep xsha1
|
||||
movaps (%rsp),%xmm0
|
||||
mov 16(%rsp),%eax
|
||||
add \$128+8,%rsp
|
||||
movups %xmm0,(%rdx) # copy-out context
|
||||
mov %eax,16(%rdx)
|
||||
ret
|
||||
.size padlock_sha1_blocks,.-padlock_sha1_blocks
|
||||
|
||||
.globl padlock_sha256_oneshot
|
||||
.type padlock_sha256_oneshot,\@function,3
|
||||
.align 16
|
||||
padlock_sha256_oneshot:
|
||||
mov %rdx,%rcx
|
||||
mov %rdi,%rdx # put aside %rdi
|
||||
movups (%rdi),%xmm0 # copy-in context
|
||||
sub \$128+8,%rsp
|
||||
movups 16(%rdi),%xmm1
|
||||
movaps %xmm0,(%rsp)
|
||||
mov %rsp,%rdi
|
||||
movaps %xmm1,16(%rsp)
|
||||
xor %rax,%rax
|
||||
.byte 0xf3,0x0f,0xa6,0xd0 # rep xsha256
|
||||
movaps (%rsp),%xmm0
|
||||
movaps 16(%rsp),%xmm1
|
||||
add \$128+8,%rsp
|
||||
movups %xmm0,(%rdx) # copy-out context
|
||||
movups %xmm1,16(%rdx)
|
||||
ret
|
||||
.size padlock_sha256_oneshot,.-padlock_sha256_oneshot
|
||||
|
||||
.globl padlock_sha256_blocks
|
||||
.type padlock_sha256_blocks,\@function,3
|
||||
.align 16
|
||||
padlock_sha256_blocks:
|
||||
mov %rdx,%rcx
|
||||
mov %rdi,%rdx # put aside %rdi
|
||||
movups (%rdi),%xmm0 # copy-in context
|
||||
sub \$128+8,%rsp
|
||||
movups 16(%rdi),%xmm1
|
||||
movaps %xmm0,(%rsp)
|
||||
mov %rsp,%rdi
|
||||
movaps %xmm1,16(%rsp)
|
||||
mov \$-1,%rax
|
||||
.byte 0xf3,0x0f,0xa6,0xd0 # rep xsha256
|
||||
movaps (%rsp),%xmm0
|
||||
movaps 16(%rsp),%xmm1
|
||||
add \$128+8,%rsp
|
||||
movups %xmm0,(%rdx) # copy-out context
|
||||
movups %xmm1,16(%rdx)
|
||||
ret
|
||||
.size padlock_sha256_blocks,.-padlock_sha256_blocks
|
||||
|
||||
.globl padlock_sha512_blocks
|
||||
.type padlock_sha512_blocks,\@function,3
|
||||
.align 16
|
||||
padlock_sha512_blocks:
|
||||
mov %rdx,%rcx
|
||||
mov %rdi,%rdx # put aside %rdi
|
||||
movups (%rdi),%xmm0 # copy-in context
|
||||
sub \$128+8,%rsp
|
||||
movups 16(%rdi),%xmm1
|
||||
movups 32(%rdi),%xmm2
|
||||
movups 48(%rdi),%xmm3
|
||||
movaps %xmm0,(%rsp)
|
||||
mov %rsp,%rdi
|
||||
movaps %xmm1,16(%rsp)
|
||||
movaps %xmm2,32(%rsp)
|
||||
movaps %xmm3,48(%rsp)
|
||||
.byte 0xf3,0x0f,0xa6,0xe0 # rep xha512
|
||||
movaps (%rsp),%xmm0
|
||||
movaps 16(%rsp),%xmm1
|
||||
movaps 32(%rsp),%xmm2
|
||||
movaps 48(%rsp),%xmm3
|
||||
add \$128+8,%rsp
|
||||
movups %xmm0,(%rdx) # copy-out context
|
||||
movups %xmm1,16(%rdx)
|
||||
movups %xmm2,32(%rdx)
|
||||
movups %xmm3,48(%rdx)
|
||||
ret
|
||||
.size padlock_sha512_blocks,.-padlock_sha512_blocks
|
||||
___
|
||||
|
||||
sub generate_mode {
|
||||
my ($mode,$opcode) = @_;
|
||||
# int padlock_$mode_encrypt(void *out, const void *inp,
|
||||
# struct padlock_cipher_data *ctx, size_t len);
|
||||
$code.=<<___;
|
||||
.globl padlock_${mode}_encrypt
|
||||
.type padlock_${mode}_encrypt,\@function,4
|
||||
.align 16
|
||||
padlock_${mode}_encrypt:
|
||||
push %rbp
|
||||
push %rbx
|
||||
|
||||
xor %eax,%eax
|
||||
test \$15,$ctx
|
||||
jnz .L${mode}_abort
|
||||
test \$15,$len
|
||||
jnz .L${mode}_abort
|
||||
lea .Lpadlock_saved_context(%rip),%rax
|
||||
pushf
|
||||
cld
|
||||
call _padlock_verify_ctx
|
||||
lea 16($ctx),$ctx # control word
|
||||
xor %eax,%eax
|
||||
xor %ebx,%ebx
|
||||
testl \$`1<<5`,($ctx) # align bit in control word
|
||||
jnz .L${mode}_aligned
|
||||
test \$0x0f,$out
|
||||
setz %al # !out_misaligned
|
||||
test \$0x0f,$inp
|
||||
setz %bl # !inp_misaligned
|
||||
test %ebx,%eax
|
||||
jnz .L${mode}_aligned
|
||||
neg %rax
|
||||
mov \$$PADLOCK_CHUNK,$chunk
|
||||
not %rax # out_misaligned?-1:0
|
||||
lea (%rsp),%rbp
|
||||
cmp $chunk,$len
|
||||
cmovc $len,$chunk # chunk=len>PADLOCK_CHUNK?PADLOCK_CHUNK:len
|
||||
and $chunk,%rax # out_misaligned?chunk:0
|
||||
mov $len,$chunk
|
||||
neg %rax
|
||||
and \$$PADLOCK_CHUNK-1,$chunk # chunk%=PADLOCK_CHUNK
|
||||
lea (%rax,%rbp),%rsp
|
||||
mov \$$PADLOCK_CHUNK,%rax
|
||||
cmovz %rax,$chunk # chunk=chunk?:PADLOCK_CHUNK
|
||||
___
|
||||
$code.=<<___ if ($mode eq "ctr32");
|
||||
.L${mode}_reenter:
|
||||
mov -4($ctx),%eax # pull 32-bit counter
|
||||
bswap %eax
|
||||
neg %eax
|
||||
and \$`$PADLOCK_CHUNK/16-1`,%eax
|
||||
mov \$$PADLOCK_CHUNK,$chunk
|
||||
shl \$4,%eax
|
||||
cmovz $chunk,%rax
|
||||
cmp %rax,$len
|
||||
cmova %rax,$chunk # don't let counter cross PADLOCK_CHUNK
|
||||
cmovbe $len,$chunk
|
||||
___
|
||||
$code.=<<___ if ($PADLOCK_PREFETCH{$mode});
|
||||
cmp $chunk,$len
|
||||
ja .L${mode}_loop
|
||||
mov $inp,%rax # check if prefetch crosses page
|
||||
cmp %rsp,%rbp
|
||||
cmove $out,%rax
|
||||
add $len,%rax
|
||||
neg %rax
|
||||
and \$0xfff,%rax # distance to page boundary
|
||||
cmp \$$PADLOCK_PREFETCH{$mode},%rax
|
||||
mov \$-$PADLOCK_PREFETCH{$mode},%rax
|
||||
cmovae $chunk,%rax # mask=distance<prefetch?-prefetch:-1
|
||||
and %rax,$chunk
|
||||
jz .L${mode}_unaligned_tail
|
||||
___
|
||||
$code.=<<___;
|
||||
jmp .L${mode}_loop
|
||||
.align 16
|
||||
.L${mode}_loop:
|
||||
cmp $len,$chunk # ctr32 artefact
|
||||
cmova $len,$chunk # ctr32 artefact
|
||||
mov $out,%r8 # save parameters
|
||||
mov $inp,%r9
|
||||
mov $len,%r10
|
||||
mov $chunk,$len
|
||||
mov $chunk,%r11
|
||||
test \$0x0f,$out # out_misaligned
|
||||
cmovnz %rsp,$out
|
||||
test \$0x0f,$inp # inp_misaligned
|
||||
jz .L${mode}_inp_aligned
|
||||
shr \$3,$len
|
||||
.byte 0xf3,0x48,0xa5 # rep movsq
|
||||
sub $chunk,$out
|
||||
mov $chunk,$len
|
||||
mov $out,$inp
|
||||
.L${mode}_inp_aligned:
|
||||
lea -16($ctx),%rax # ivp
|
||||
lea 16($ctx),%rbx # key
|
||||
shr \$4,$len
|
||||
.byte 0xf3,0x0f,0xa7,$opcode # rep xcrypt*
|
||||
___
|
||||
$code.=<<___ if ($mode !~ /ecb|ctr/);
|
||||
movdqa (%rax),%xmm0
|
||||
movdqa %xmm0,-16($ctx) # copy [or refresh] iv
|
||||
___
|
||||
$code.=<<___ if ($mode eq "ctr32");
|
||||
mov -4($ctx),%eax # pull 32-bit counter
|
||||
test \$0xffff0000,%eax
|
||||
jnz .L${mode}_no_carry
|
||||
bswap %eax
|
||||
add \$0x10000,%eax
|
||||
bswap %eax
|
||||
mov %eax,-4($ctx)
|
||||
.L${mode}_no_carry:
|
||||
___
|
||||
$code.=<<___;
|
||||
mov %r8,$out # restore parameters
|
||||
mov %r11,$chunk
|
||||
test \$0x0f,$out
|
||||
jz .L${mode}_out_aligned
|
||||
mov $chunk,$len
|
||||
lea (%rsp),$inp
|
||||
shr \$3,$len
|
||||
.byte 0xf3,0x48,0xa5 # rep movsq
|
||||
sub $chunk,$out
|
||||
.L${mode}_out_aligned:
|
||||
mov %r9,$inp
|
||||
mov %r10,$len
|
||||
add $chunk,$out
|
||||
add $chunk,$inp
|
||||
sub $chunk,$len
|
||||
mov \$$PADLOCK_CHUNK,$chunk
|
||||
___
|
||||
if (!$PADLOCK_PREFETCH{$mode}) {
|
||||
$code.=<<___;
|
||||
jnz .L${mode}_loop
|
||||
___
|
||||
} else {
|
||||
$code.=<<___;
|
||||
jz .L${mode}_break
|
||||
cmp $chunk,$len
|
||||
jae .L${mode}_loop
|
||||
___
|
||||
$code.=<<___ if ($mode eq "ctr32");
|
||||
mov $len,$chunk
|
||||
mov $inp,%rax # check if prefetch crosses page
|
||||
cmp %rsp,%rbp
|
||||
cmove $out,%rax
|
||||
add $len,%rax
|
||||
neg %rax
|
||||
and \$0xfff,%rax # distance to page boundary
|
||||
cmp \$$PADLOCK_PREFETCH{$mode},%rax
|
||||
mov \$-$PADLOCK_PREFETCH{$mode},%rax
|
||||
cmovae $chunk,%rax
|
||||
and %rax,$chunk
|
||||
jnz .L${mode}_loop
|
||||
___
|
||||
$code.=<<___;
|
||||
.L${mode}_unaligned_tail:
|
||||
xor %eax,%eax
|
||||
cmp %rsp,%rbp
|
||||
cmove $len,%rax
|
||||
mov $out,%r8 # save parameters
|
||||
mov $len,$chunk
|
||||
sub %rax,%rsp # alloca
|
||||
shr \$3,$len
|
||||
lea (%rsp),$out
|
||||
.byte 0xf3,0x48,0xa5 # rep movsq
|
||||
mov %rsp,$inp
|
||||
mov %r8, $out # restore parameters
|
||||
mov $chunk,$len
|
||||
jmp .L${mode}_loop
|
||||
.align 16
|
||||
.L${mode}_break:
|
||||
___
|
||||
}
|
||||
$code.=<<___;
|
||||
cmp %rbp,%rsp
|
||||
je .L${mode}_done
|
||||
|
||||
pxor %xmm0,%xmm0
|
||||
lea (%rsp),%rax
|
||||
.L${mode}_bzero:
|
||||
movaps %xmm0,(%rax)
|
||||
lea 16(%rax),%rax
|
||||
cmp %rax,%rbp
|
||||
ja .L${mode}_bzero
|
||||
|
||||
.L${mode}_done:
|
||||
lea (%rbp),%rsp
|
||||
jmp .L${mode}_exit
|
||||
|
||||
.align 16
|
||||
.L${mode}_aligned:
|
||||
___
|
||||
$code.=<<___ if ($mode eq "ctr32");
|
||||
mov -4($ctx),%eax # pull 32-bit counter
|
||||
bswap %eax
|
||||
neg %eax
|
||||
and \$0xffff,%eax
|
||||
mov \$`16*0x10000`,$chunk
|
||||
shl \$4,%eax
|
||||
cmovz $chunk,%rax
|
||||
cmp %rax,$len
|
||||
cmova %rax,$chunk # don't let counter cross 2^16
|
||||
cmovbe $len,$chunk
|
||||
jbe .L${mode}_aligned_skip
|
||||
|
||||
.L${mode}_aligned_loop:
|
||||
mov $len,%r10 # save parameters
|
||||
mov $chunk,$len
|
||||
mov $chunk,%r11
|
||||
|
||||
lea -16($ctx),%rax # ivp
|
||||
lea 16($ctx),%rbx # key
|
||||
shr \$4,$len # len/=AES_BLOCK_SIZE
|
||||
.byte 0xf3,0x0f,0xa7,$opcode # rep xcrypt*
|
||||
|
||||
mov -4($ctx),%eax # pull 32-bit counter
|
||||
bswap %eax
|
||||
add \$0x10000,%eax
|
||||
bswap %eax
|
||||
mov %eax,-4($ctx)
|
||||
|
||||
mov %r10,$len # restore parameters
|
||||
sub %r11,$len
|
||||
mov \$`16*0x10000`,$chunk
|
||||
jz .L${mode}_exit
|
||||
cmp $chunk,$len
|
||||
jae .L${mode}_aligned_loop
|
||||
|
||||
.L${mode}_aligned_skip:
|
||||
___
|
||||
$code.=<<___ if ($PADLOCK_PREFETCH{$mode});
|
||||
lea ($inp,$len),%rbp
|
||||
neg %rbp
|
||||
and \$0xfff,%rbp # distance to page boundary
|
||||
xor %eax,%eax
|
||||
cmp \$$PADLOCK_PREFETCH{$mode},%rbp
|
||||
mov \$$PADLOCK_PREFETCH{$mode}-1,%rbp
|
||||
cmovae %rax,%rbp
|
||||
and $len,%rbp # remainder
|
||||
sub %rbp,$len
|
||||
jz .L${mode}_aligned_tail
|
||||
___
|
||||
$code.=<<___;
|
||||
lea -16($ctx),%rax # ivp
|
||||
lea 16($ctx),%rbx # key
|
||||
shr \$4,$len # len/=AES_BLOCK_SIZE
|
||||
.byte 0xf3,0x0f,0xa7,$opcode # rep xcrypt*
|
||||
___
|
||||
$code.=<<___ if ($mode !~ /ecb|ctr/);
|
||||
movdqa (%rax),%xmm0
|
||||
movdqa %xmm0,-16($ctx) # copy [or refresh] iv
|
||||
___
|
||||
$code.=<<___ if ($PADLOCK_PREFETCH{$mode});
|
||||
test %rbp,%rbp # check remainder
|
||||
jz .L${mode}_exit
|
||||
|
||||
.L${mode}_aligned_tail:
|
||||
mov $out,%r8
|
||||
mov %rbp,$chunk
|
||||
mov %rbp,$len
|
||||
lea (%rsp),%rbp
|
||||
sub $len,%rsp
|
||||
shr \$3,$len
|
||||
lea (%rsp),$out
|
||||
.byte 0xf3,0x48,0xa5 # rep movsq
|
||||
lea (%r8),$out
|
||||
lea (%rsp),$inp
|
||||
mov $chunk,$len
|
||||
jmp .L${mode}_loop
|
||||
___
|
||||
$code.=<<___;
|
||||
.L${mode}_exit:
|
||||
mov \$1,%eax
|
||||
lea 8(%rsp),%rsp
|
||||
.L${mode}_abort:
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
ret
|
||||
.size padlock_${mode}_encrypt,.-padlock_${mode}_encrypt
|
||||
___
|
||||
}
|
||||
|
||||
&generate_mode("ecb",0xc8);
|
||||
&generate_mode("cbc",0xd0);
|
||||
&generate_mode("cfb",0xe0);
|
||||
&generate_mode("ofb",0xe8);
|
||||
&generate_mode("ctr32",0xd8); # all 64-bit CPUs have working CTR...
|
||||
|
||||
$code.=<<___;
|
||||
.asciz "VIA Padlock x86_64 module, CRYPTOGAMS by <https://github.com/dot-asm>"
|
||||
.align 16
|
||||
.data
|
||||
.align 8
|
||||
.Lpadlock_saved_context:
|
||||
.quad 0
|
||||
___
|
||||
$code =~ s/\`([^\`]*)\`/eval($1)/gem;
|
||||
|
||||
print $code;
|
||||
|
||||
close STDOUT;
|
||||
@@ -1,103 +0,0 @@
|
||||
IF[{- !$disabled{"engine"} -}]
|
||||
$PADLOCKASM=
|
||||
IF[{- !$disabled{asm} -}]
|
||||
$PADLOCKASM_x86=e_padlock-x86.S
|
||||
$PADLOCKASM_x86_64=e_padlock-x86_64.s
|
||||
|
||||
# Now that we have defined all the arch specific variables, use the
|
||||
# appropriate one, and define the appropriate macros
|
||||
IF[$PADLOCKASM_{- $target{asm_arch} -}]
|
||||
$PADLOCKASM=$PADLOCKASM_{- $target{asm_arch} -}
|
||||
$PADLOCKDEF=PADLOCK_ASM
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
IF[{- $disabled{"dynamic-engine"} -}]
|
||||
LIBS=../libcrypto
|
||||
IF[{- !$disabled{padlockeng} -}]
|
||||
SOURCE[../libcrypto]=e_padlock.c $PADLOCKASM
|
||||
DEFINE[../libcrypto]=$PADLOCKDEF
|
||||
ENDIF
|
||||
IF[{- !$disabled{capieng} -}]
|
||||
SOURCE[../libcrypto]=e_capi.c
|
||||
ENDIF
|
||||
IF[{- !$disabled{afalgeng} -}]
|
||||
SOURCE[../libcrypto]=e_afalg.c
|
||||
ENDIF
|
||||
IF[{- !$disabled{"devcryptoeng"} -}]
|
||||
SOURCE[../libcrypto]=e_devcrypto.c
|
||||
ENDIF
|
||||
ELSE
|
||||
IF[{- !$disabled{padlockeng} -}]
|
||||
MODULES{engine}=padlock
|
||||
SOURCE[padlock]=e_padlock.c $PADLOCKASM
|
||||
DEFINE[padlock]=$PADLOCKDEF
|
||||
DEPEND[padlock]=../libcrypto
|
||||
INCLUDE[padlock]=../include
|
||||
IF[{- defined $target{shared_defflag} -}]
|
||||
SOURCE[padlock]=padlock.ld
|
||||
GENERATE[padlock.ld]=../util/engines.num
|
||||
ENDIF
|
||||
ENDIF
|
||||
IF[{- !$disabled{capieng} -}]
|
||||
MODULES{engine}=capi
|
||||
SOURCE[capi]=e_capi.c
|
||||
DEPEND[capi]=../libcrypto
|
||||
INCLUDE[capi]=../include
|
||||
IF[{- defined $target{shared_defflag} -}]
|
||||
SOURCE[capi]=capi.ld
|
||||
GENERATE[capi.ld]=../util/engines.num
|
||||
ENDIF
|
||||
ENDIF
|
||||
IF[{- !$disabled{afalgeng} -}]
|
||||
MODULES{engine}=afalg
|
||||
SOURCE[afalg]=e_afalg.c
|
||||
DEPEND[afalg]=../libcrypto
|
||||
INCLUDE[afalg]= ../include
|
||||
IF[{- defined $target{shared_defflag} -}]
|
||||
SOURCE[afalg]=afalg.ld
|
||||
GENERATE[afalg.ld]=../util/engines.num
|
||||
ENDIF
|
||||
ENDIF
|
||||
IF[{- !$disabled{"devcryptoeng"} -}]
|
||||
MODULES{engine}=devcrypto
|
||||
SOURCE[devcrypto]=e_devcrypto.c
|
||||
DEPEND[devcrypto]=../libcrypto
|
||||
INCLUDE[devcrypto]=../include
|
||||
IF[{- defined $target{shared_defflag} -}]
|
||||
SOURCE[devcrypto]=devcrypto.ld
|
||||
GENERATE[devcrypto.ld]=../util/engines.num
|
||||
ENDIF
|
||||
ENDIF
|
||||
IF[{- !$disabled{"loadereng"} -}]
|
||||
MODULES{engine}=loader_attic
|
||||
SOURCE[loader_attic]=e_loader_attic.c ../crypto/pem/pvkfmt.c
|
||||
DEFINE[loader_attic]=OPENSSL_NO_PROVIDER_CODE
|
||||
DEPEND[loader_attic]=../libcrypto
|
||||
INCLUDE[loader_attic]=../include
|
||||
IF[{- defined $target{shared_defflag} -}]
|
||||
SOURCE[loader_attic]=loader_attic.ld
|
||||
GENERATE[loader_attic.ld]=../util/engines.num
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
MODULES{noinst,engine}=ossltest dasync
|
||||
SOURCE[dasync]=e_dasync.c
|
||||
DEPEND[dasync]=../libcrypto
|
||||
INCLUDE[dasync]=../include
|
||||
IF[{- defined $target{shared_defflag} -}]
|
||||
SOURCE[dasync]=dasync.ld
|
||||
GENERATE[dasync.ld]=../util/engines.num
|
||||
ENDIF
|
||||
|
||||
SOURCE[ossltest]=e_ossltest.c
|
||||
DEPEND[ossltest]=../libcrypto
|
||||
INCLUDE[ossltest]=../include
|
||||
IF[{- defined $target{shared_defflag} -}]
|
||||
SOURCE[ossltest]=ossltest.ld
|
||||
GENERATE[ossltest.ld]=../util/engines.num
|
||||
ENDIF
|
||||
ENDIF
|
||||
GENERATE[e_padlock-x86.S]=asm/e_padlock-x86.pl
|
||||
GENERATE[e_padlock-x86_64.s]=asm/e_padlock-x86_64.pl
|
||||
ENDIF
|
||||
@@ -1,935 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* We need to use some deprecated APIs */
|
||||
#define OPENSSL_SUPPRESS_DEPRECATED
|
||||
|
||||
/* Required for vmsplice */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/async.h>
|
||||
#include <openssl/err.h>
|
||||
#include "internal/nelem.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <linux/version.h>
|
||||
#define K_MAJ 4
|
||||
#define K_MIN1 1
|
||||
#define K_MIN2 0
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2) || \
|
||||
!defined(AF_ALG)
|
||||
# ifndef PEDANTIC
|
||||
# warning "AFALG ENGINE requires Kernel Headers >= 4.1.0"
|
||||
# warning "Skipping Compilation of AFALG engine"
|
||||
# endif
|
||||
void engine_load_afalg_int(void);
|
||||
void engine_load_afalg_int(void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
|
||||
# include <linux/if_alg.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/utsname.h>
|
||||
|
||||
# include <linux/aio_abi.h>
|
||||
# include <sys/syscall.h>
|
||||
# include <errno.h>
|
||||
|
||||
/* clang-format off */
|
||||
# include "e_afalg.h"
|
||||
# include "e_afalg_err.c"
|
||||
/* clang-format on */
|
||||
|
||||
# ifndef SOL_ALG
|
||||
# define SOL_ALG 279
|
||||
# endif
|
||||
|
||||
# ifdef ALG_ZERO_COPY
|
||||
# ifndef SPLICE_F_GIFT
|
||||
# define SPLICE_F_GIFT (0x08)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# define ALG_AES_IV_LEN 16
|
||||
# define ALG_IV_LEN(len) (sizeof(struct af_alg_iv) + (len))
|
||||
# define ALG_OP_TYPE unsigned int
|
||||
# define ALG_OP_LEN (sizeof(ALG_OP_TYPE))
|
||||
|
||||
void engine_load_afalg_int(void);
|
||||
|
||||
/* Local Linkage Functions */
|
||||
static int afalg_init_aio(afalg_aio *aio);
|
||||
static int afalg_fin_cipher_aio(afalg_aio *ptr, int sfd,
|
||||
unsigned char *buf, size_t len);
|
||||
static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype,
|
||||
const char *ciphername);
|
||||
static int afalg_destroy(ENGINE *e);
|
||||
static int afalg_init(ENGINE *e);
|
||||
static int afalg_finish(ENGINE *e);
|
||||
static const EVP_CIPHER *afalg_aes_cbc(int nid);
|
||||
static cbc_handles *get_cipher_handle(int nid);
|
||||
static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
|
||||
const int **nids, int nid);
|
||||
static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc);
|
||||
static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl);
|
||||
static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx);
|
||||
static int afalg_chk_platform(void);
|
||||
|
||||
/* Engine Id and Name */
|
||||
static const char *engine_afalg_id = "afalg";
|
||||
static const char *engine_afalg_name = "AFALG engine support";
|
||||
|
||||
static int afalg_cipher_nids[] = {
|
||||
NID_aes_128_cbc,
|
||||
NID_aes_192_cbc,
|
||||
NID_aes_256_cbc,
|
||||
};
|
||||
|
||||
static cbc_handles cbc_handle[] = {{AES_KEY_SIZE_128, NULL},
|
||||
{AES_KEY_SIZE_192, NULL},
|
||||
{AES_KEY_SIZE_256, NULL}};
|
||||
|
||||
static ossl_inline int io_setup(unsigned n, aio_context_t *ctx)
|
||||
{
|
||||
return syscall(__NR_io_setup, n, ctx);
|
||||
}
|
||||
|
||||
static ossl_inline int eventfd(int n)
|
||||
{
|
||||
return syscall(__NR_eventfd2, n, 0);
|
||||
}
|
||||
|
||||
static ossl_inline int io_destroy(aio_context_t ctx)
|
||||
{
|
||||
return syscall(__NR_io_destroy, ctx);
|
||||
}
|
||||
|
||||
static ossl_inline int io_read(aio_context_t ctx, long n, struct iocb **iocb)
|
||||
{
|
||||
return syscall(__NR_io_submit, ctx, n, iocb);
|
||||
}
|
||||
|
||||
/* A version of 'struct timespec' with 32-bit time_t and nanoseconds. */
|
||||
struct __timespec32 {
|
||||
__kernel_long_t tv_sec;
|
||||
__kernel_long_t tv_nsec;
|
||||
};
|
||||
|
||||
static ossl_inline int io_getevents(aio_context_t ctx, long min, long max,
|
||||
struct io_event *events,
|
||||
struct timespec *timeout)
|
||||
{
|
||||
#if defined(__NR_io_pgetevents_time64)
|
||||
/* Check if we are a 32-bit architecture with a 64-bit time_t */
|
||||
if (sizeof(*timeout) != sizeof(struct __timespec32)) {
|
||||
int ret = syscall(__NR_io_pgetevents_time64, ctx, min, max, events,
|
||||
timeout, NULL);
|
||||
if (ret == 0 || errno != ENOSYS)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__NR_io_getevents)
|
||||
if (sizeof(*timeout) == sizeof(struct __timespec32))
|
||||
/*
|
||||
* time_t matches our architecture length, we can just use
|
||||
* __NR_io_getevents
|
||||
*/
|
||||
return syscall(__NR_io_getevents, ctx, min, max, events, timeout);
|
||||
else {
|
||||
/*
|
||||
* We don't have __NR_io_pgetevents_time64, but we are using a
|
||||
* 64-bit time_t on a 32-bit architecture. If we can fit the
|
||||
* timeout value in a 32-bit time_t, then let's do that
|
||||
* and then use the __NR_io_getevents syscall.
|
||||
*/
|
||||
if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
|
||||
struct __timespec32 ts32;
|
||||
|
||||
ts32.tv_sec = (__kernel_long_t) timeout->tv_sec;
|
||||
ts32.tv_nsec = (__kernel_long_t) timeout->tv_nsec;
|
||||
|
||||
return syscall(__NR_io_getevents, ctx, min, max, events, &ts32);
|
||||
} else {
|
||||
return syscall(__NR_io_getevents, ctx, min, max, events, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void afalg_waitfd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key,
|
||||
OSSL_ASYNC_FD waitfd, void *custom)
|
||||
{
|
||||
close(waitfd);
|
||||
}
|
||||
|
||||
static int afalg_setup_async_event_notification(afalg_aio *aio)
|
||||
{
|
||||
ASYNC_JOB *job;
|
||||
ASYNC_WAIT_CTX *waitctx;
|
||||
void *custom = NULL;
|
||||
int ret;
|
||||
|
||||
if ((job = ASYNC_get_current_job()) != NULL) {
|
||||
/* Async mode */
|
||||
waitctx = ASYNC_get_wait_ctx(job);
|
||||
if (waitctx == NULL) {
|
||||
ALG_WARN("%s(%d): ASYNC_get_wait_ctx error", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
/* Get waitfd from ASYNC_WAIT_CTX if it is already set */
|
||||
ret = ASYNC_WAIT_CTX_get_fd(waitctx, engine_afalg_id,
|
||||
&aio->efd, &custom);
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* waitfd is not set in ASYNC_WAIT_CTX, create a new one
|
||||
* and set it. efd will be signaled when AIO operation completes
|
||||
*/
|
||||
aio->efd = eventfd(0);
|
||||
if (aio->efd == -1) {
|
||||
ALG_PERR("%s(%d): Failed to get eventfd : ", __FILE__,
|
||||
__LINE__);
|
||||
AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION,
|
||||
AFALG_R_EVENTFD_FAILED);
|
||||
return 0;
|
||||
}
|
||||
ret = ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_afalg_id,
|
||||
aio->efd, custom,
|
||||
afalg_waitfd_cleanup);
|
||||
if (ret == 0) {
|
||||
ALG_WARN("%s(%d): Failed to set wait fd", __FILE__, __LINE__);
|
||||
close(aio->efd);
|
||||
return 0;
|
||||
}
|
||||
/* make fd non-blocking in async mode */
|
||||
if (fcntl(aio->efd, F_SETFL, O_NONBLOCK) != 0) {
|
||||
ALG_WARN("%s(%d): Failed to set event fd as NONBLOCKING",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
aio->mode = MODE_ASYNC;
|
||||
} else {
|
||||
/* Sync mode */
|
||||
aio->efd = eventfd(0);
|
||||
if (aio->efd == -1) {
|
||||
ALG_PERR("%s(%d): Failed to get eventfd : ", __FILE__, __LINE__);
|
||||
AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION,
|
||||
AFALG_R_EVENTFD_FAILED);
|
||||
return 0;
|
||||
}
|
||||
aio->mode = MODE_SYNC;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int afalg_init_aio(afalg_aio *aio)
|
||||
{
|
||||
int r = -1;
|
||||
|
||||
/* Initialise for AIO */
|
||||
aio->aio_ctx = 0;
|
||||
r = io_setup(MAX_INFLIGHTS, &aio->aio_ctx);
|
||||
if (r < 0) {
|
||||
ALG_PERR("%s(%d): io_setup error : ", __FILE__, __LINE__);
|
||||
AFALGerr(AFALG_F_AFALG_INIT_AIO, AFALG_R_IO_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(aio->cbt, 0, sizeof(aio->cbt));
|
||||
aio->efd = -1;
|
||||
aio->mode = MODE_UNINIT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int afalg_fin_cipher_aio(afalg_aio *aio, int sfd, unsigned char *buf,
|
||||
size_t len)
|
||||
{
|
||||
int r;
|
||||
int retry = 0;
|
||||
unsigned int done = 0;
|
||||
struct iocb *cb;
|
||||
struct timespec timeout;
|
||||
struct io_event events[MAX_INFLIGHTS];
|
||||
u_int64_t eval = 0;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_nsec = 0;
|
||||
|
||||
/* if efd has not been initialised yet do it here */
|
||||
if (aio->mode == MODE_UNINIT) {
|
||||
r = afalg_setup_async_event_notification(aio);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
cb = &(aio->cbt[0 % MAX_INFLIGHTS]);
|
||||
memset(cb, '\0', sizeof(*cb));
|
||||
cb->aio_fildes = sfd;
|
||||
cb->aio_lio_opcode = IOCB_CMD_PREAD;
|
||||
/*
|
||||
* The pointer has to be converted to unsigned value first to avoid
|
||||
* sign extension on cast to 64 bit value in 32-bit builds
|
||||
*/
|
||||
cb->aio_buf = (size_t)buf;
|
||||
cb->aio_offset = 0;
|
||||
cb->aio_data = 0;
|
||||
cb->aio_nbytes = len;
|
||||
cb->aio_flags = IOCB_FLAG_RESFD;
|
||||
cb->aio_resfd = aio->efd;
|
||||
|
||||
/*
|
||||
* Perform AIO read on AFALG socket, this in turn performs an async
|
||||
* crypto operation in kernel space
|
||||
*/
|
||||
r = io_read(aio->aio_ctx, 1, &cb);
|
||||
if (r < 0) {
|
||||
ALG_PWARN("%s(%d): io_read failed : ", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
/* While AIO read is being performed pause job */
|
||||
ASYNC_pause_job();
|
||||
|
||||
/* Check for completion of AIO read */
|
||||
r = read(aio->efd, &eval, sizeof(eval));
|
||||
if (r < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
continue;
|
||||
ALG_PERR("%s(%d): read failed for event fd : ", __FILE__, __LINE__);
|
||||
return 0;
|
||||
} else if (r == 0 || eval <= 0) {
|
||||
ALG_WARN("%s(%d): eventfd read %d bytes, eval = %lu\n", __FILE__,
|
||||
__LINE__, r, eval);
|
||||
}
|
||||
if (eval > 0) {
|
||||
|
||||
#ifdef OSSL_SANITIZE_MEMORY
|
||||
/*
|
||||
* In a memory sanitiser build, the changes to memory made by the
|
||||
* system call aren't reliably detected. By initialising the
|
||||
* memory here, the sanitiser is told that they are okay.
|
||||
*/
|
||||
memset(events, 0, sizeof(events));
|
||||
#endif
|
||||
|
||||
/* Get results of AIO read */
|
||||
r = io_getevents(aio->aio_ctx, 1, MAX_INFLIGHTS,
|
||||
events, &timeout);
|
||||
if (r > 0) {
|
||||
/*
|
||||
* events.res indicates the actual status of the operation.
|
||||
* Handle the error condition first.
|
||||
*/
|
||||
if (events[0].res < 0) {
|
||||
/*
|
||||
* Underlying operation cannot be completed at the time
|
||||
* of previous submission. Resubmit for the operation.
|
||||
*/
|
||||
if (events[0].res == -EBUSY && retry++ < 3) {
|
||||
r = io_read(aio->aio_ctx, 1, &cb);
|
||||
if (r < 0) {
|
||||
ALG_PERR("%s(%d): retry %d for io_read failed : ",
|
||||
__FILE__, __LINE__, retry);
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
char strbuf[32];
|
||||
/*
|
||||
* sometimes __s64 is defined as long long int
|
||||
* but on some archs ( like mips64 or powerpc64 ) it's just long int
|
||||
*
|
||||
* to be able to use BIO_snprintf() with %lld without warnings
|
||||
* copy events[0].res to an long long int variable
|
||||
*
|
||||
* because long long int should always be at least 64 bit this should work
|
||||
*/
|
||||
long long int op_ret = events[0].res;
|
||||
|
||||
/*
|
||||
* Retries exceed for -EBUSY or unrecoverable error
|
||||
* condition for this instance of operation.
|
||||
*/
|
||||
ALG_WARN
|
||||
("%s(%d): Crypto Operation failed with code %lld\n",
|
||||
__FILE__, __LINE__, events[0].res);
|
||||
BIO_snprintf(strbuf, sizeof(strbuf), "%lld", op_ret);
|
||||
switch (events[0].res) {
|
||||
case -ENOMEM:
|
||||
AFALGerr(0, AFALG_R_KERNEL_OP_FAILED);
|
||||
ERR_add_error_data(3, "-ENOMEM ( code ", strbuf, " )");
|
||||
break;
|
||||
default:
|
||||
AFALGerr(0, AFALG_R_KERNEL_OP_FAILED);
|
||||
ERR_add_error_data(2, "code ", strbuf);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Operation successful. */
|
||||
done = 1;
|
||||
} else if (r < 0) {
|
||||
ALG_PERR("%s(%d): io_getevents failed : ", __FILE__, __LINE__);
|
||||
return 0;
|
||||
} else {
|
||||
ALG_WARN("%s(%d): io_geteventd read 0 bytes\n", __FILE__,
|
||||
__LINE__);
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ossl_inline void afalg_set_op_sk(struct cmsghdr *cmsg,
|
||||
const ALG_OP_TYPE op)
|
||||
{
|
||||
cmsg->cmsg_level = SOL_ALG;
|
||||
cmsg->cmsg_type = ALG_SET_OP;
|
||||
cmsg->cmsg_len = CMSG_LEN(ALG_OP_LEN);
|
||||
memcpy(CMSG_DATA(cmsg), &op, ALG_OP_LEN);
|
||||
}
|
||||
|
||||
static void afalg_set_iv_sk(struct cmsghdr *cmsg, const unsigned char *iv,
|
||||
const unsigned int len)
|
||||
{
|
||||
struct af_alg_iv *aiv;
|
||||
|
||||
cmsg->cmsg_level = SOL_ALG;
|
||||
cmsg->cmsg_type = ALG_SET_IV;
|
||||
cmsg->cmsg_len = CMSG_LEN(ALG_IV_LEN(len));
|
||||
aiv = (struct af_alg_iv *)CMSG_DATA(cmsg);
|
||||
aiv->ivlen = len;
|
||||
memcpy(aiv->iv, iv, len);
|
||||
}
|
||||
|
||||
static ossl_inline int afalg_set_key(afalg_ctx *actx, const unsigned char *key,
|
||||
const int klen)
|
||||
{
|
||||
int ret;
|
||||
ret = setsockopt(actx->bfd, SOL_ALG, ALG_SET_KEY, key, klen);
|
||||
if (ret < 0) {
|
||||
ALG_PERR("%s(%d): Failed to set socket option : ", __FILE__, __LINE__);
|
||||
AFALGerr(AFALG_F_AFALG_SET_KEY, AFALG_R_SOCKET_SET_KEY_FAILED);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype,
|
||||
const char *ciphername)
|
||||
{
|
||||
struct sockaddr_alg sa;
|
||||
int r = -1;
|
||||
|
||||
actx->bfd = actx->sfd = -1;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.salg_family = AF_ALG;
|
||||
OPENSSL_strlcpy((char *) sa.salg_type, ciphertype, sizeof(sa.salg_type));
|
||||
OPENSSL_strlcpy((char *) sa.salg_name, ciphername, sizeof(sa.salg_name));
|
||||
|
||||
actx->bfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
|
||||
if (actx->bfd == -1) {
|
||||
ALG_PERR("%s(%d): Failed to open socket : ", __FILE__, __LINE__);
|
||||
AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_CREATE_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = bind(actx->bfd, (struct sockaddr *)&sa, sizeof(sa));
|
||||
if (r < 0) {
|
||||
ALG_PERR("%s(%d): Failed to bind socket : ", __FILE__, __LINE__);
|
||||
AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_BIND_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
actx->sfd = accept(actx->bfd, NULL, 0);
|
||||
if (actx->sfd < 0) {
|
||||
ALG_PERR("%s(%d): Socket Accept Failed : ", __FILE__, __LINE__);
|
||||
AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_ACCEPT_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
if (actx->bfd >= 0)
|
||||
close(actx->bfd);
|
||||
if (actx->sfd >= 0)
|
||||
close(actx->sfd);
|
||||
actx->bfd = actx->sfd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int afalg_start_cipher_sk(afalg_ctx *actx, const unsigned char *in,
|
||||
size_t inl, const unsigned char *iv,
|
||||
unsigned int enc)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec iov;
|
||||
ssize_t sbytes;
|
||||
# ifdef ALG_ZERO_COPY
|
||||
int ret;
|
||||
# endif
|
||||
char cbuf[CMSG_SPACE(ALG_IV_LEN(ALG_AES_IV_LEN)) + CMSG_SPACE(ALG_OP_LEN)];
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
memset(cbuf, 0, sizeof(cbuf));
|
||||
msg.msg_control = cbuf;
|
||||
msg.msg_controllen = sizeof(cbuf);
|
||||
|
||||
/*
|
||||
* cipher direction (i.e. encrypt or decrypt) and iv are sent to the
|
||||
* kernel as part of sendmsg()'s ancillary data
|
||||
*/
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
afalg_set_op_sk(cmsg, enc);
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg);
|
||||
afalg_set_iv_sk(cmsg, iv, ALG_AES_IV_LEN);
|
||||
|
||||
/* iov that describes input data */
|
||||
iov.iov_base = (unsigned char *)in;
|
||||
iov.iov_len = inl;
|
||||
|
||||
msg.msg_flags = MSG_MORE;
|
||||
|
||||
# ifdef ALG_ZERO_COPY
|
||||
/*
|
||||
* ZERO_COPY mode
|
||||
* Works best when buffer is 4k aligned
|
||||
* OPENS: out of place processing (i.e. out != in)
|
||||
*/
|
||||
|
||||
/* Input data is not sent as part of call to sendmsg() */
|
||||
msg.msg_iovlen = 0;
|
||||
msg.msg_iov = NULL;
|
||||
|
||||
/* Sendmsg() sends iv and cipher direction to the kernel */
|
||||
sbytes = sendmsg(actx->sfd, &msg, 0);
|
||||
if (sbytes < 0) {
|
||||
ALG_PERR("%s(%d): sendmsg failed for zero copy cipher operation : ",
|
||||
__FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* vmsplice and splice are used to pin the user space input buffer for
|
||||
* kernel space processing avoiding copies from user to kernel space
|
||||
*/
|
||||
ret = vmsplice(actx->zc_pipe[1], &iov, 1, SPLICE_F_GIFT);
|
||||
if (ret < 0) {
|
||||
ALG_PERR("%s(%d): vmsplice failed : ", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = splice(actx->zc_pipe[0], NULL, actx->sfd, NULL, inl, 0);
|
||||
if (ret < 0) {
|
||||
ALG_PERR("%s(%d): splice failed : ", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
# else
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_iov = &iov;
|
||||
|
||||
/* Sendmsg() sends iv, cipher direction and input data to the kernel */
|
||||
sbytes = sendmsg(actx->sfd, &msg, 0);
|
||||
if (sbytes < 0) {
|
||||
ALG_PERR("%s(%d): sendmsg failed for cipher operation : ", __FILE__,
|
||||
__LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sbytes != (ssize_t) inl) {
|
||||
ALG_WARN("Cipher operation send bytes %zd != inlen %zd\n", sbytes,
|
||||
inl);
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
int ciphertype;
|
||||
int ret, len;
|
||||
afalg_ctx *actx;
|
||||
const char *ciphername;
|
||||
|
||||
if (ctx == NULL || key == NULL) {
|
||||
ALG_WARN("%s(%d): Null Parameter\n", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (EVP_CIPHER_CTX_get0_cipher(ctx) == NULL) {
|
||||
ALG_WARN("%s(%d): Cipher object NULL\n", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
actx = EVP_CIPHER_CTX_get_cipher_data(ctx);
|
||||
if (actx == NULL) {
|
||||
ALG_WARN("%s(%d): Cipher data NULL\n", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ciphertype = EVP_CIPHER_CTX_get_nid(ctx);
|
||||
switch (ciphertype) {
|
||||
case NID_aes_128_cbc:
|
||||
case NID_aes_192_cbc:
|
||||
case NID_aes_256_cbc:
|
||||
ciphername = "cbc(aes)";
|
||||
break;
|
||||
default:
|
||||
ALG_WARN("%s(%d): Unsupported Cipher type %d\n", __FILE__, __LINE__,
|
||||
ciphertype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ALG_AES_IV_LEN != EVP_CIPHER_CTX_get_iv_length(ctx)) {
|
||||
ALG_WARN("%s(%d): Unsupported IV length :%d\n", __FILE__, __LINE__,
|
||||
EVP_CIPHER_CTX_get_iv_length(ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Setup AFALG socket for crypto processing */
|
||||
ret = afalg_create_sk(actx, "skcipher", ciphername);
|
||||
if (ret < 1)
|
||||
return 0;
|
||||
|
||||
if ((len = EVP_CIPHER_CTX_get_key_length(ctx)) <= 0)
|
||||
goto err;
|
||||
ret = afalg_set_key(actx, key, len);
|
||||
if (ret < 1)
|
||||
goto err;
|
||||
|
||||
/* Setup AIO ctx to allow async AFALG crypto processing */
|
||||
if (afalg_init_aio(&actx->aio) == 0)
|
||||
goto err;
|
||||
|
||||
# ifdef ALG_ZERO_COPY
|
||||
pipe(actx->zc_pipe);
|
||||
# endif
|
||||
|
||||
actx->init_done = MAGIC_INIT_NUM;
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
close(actx->sfd);
|
||||
close(actx->bfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
afalg_ctx *actx;
|
||||
int ret;
|
||||
char nxtiv[ALG_AES_IV_LEN] = { 0 };
|
||||
|
||||
if (ctx == NULL || out == NULL || in == NULL) {
|
||||
ALG_WARN("NULL parameter passed to function %s(%d)\n", __FILE__,
|
||||
__LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
actx = (afalg_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
|
||||
if (actx == NULL || actx->init_done != MAGIC_INIT_NUM) {
|
||||
ALG_WARN("%s afalg ctx passed\n",
|
||||
ctx == NULL ? "NULL" : "Uninitialised");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* set iv now for decrypt operation as the input buffer can be
|
||||
* overwritten for inplace operation where in = out.
|
||||
*/
|
||||
if (EVP_CIPHER_CTX_is_encrypting(ctx) == 0) {
|
||||
memcpy(nxtiv, in + (inl - ALG_AES_IV_LEN), ALG_AES_IV_LEN);
|
||||
}
|
||||
|
||||
/* Send input data to kernel space */
|
||||
ret = afalg_start_cipher_sk(actx, (unsigned char *)in, inl,
|
||||
EVP_CIPHER_CTX_iv(ctx),
|
||||
EVP_CIPHER_CTX_is_encrypting(ctx));
|
||||
if (ret < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform async crypto operation in kernel space */
|
||||
ret = afalg_fin_cipher_aio(&actx->aio, actx->sfd, out, inl);
|
||||
if (ret < 1)
|
||||
return 0;
|
||||
|
||||
if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
|
||||
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), out + (inl - ALG_AES_IV_LEN),
|
||||
ALG_AES_IV_LEN);
|
||||
} else {
|
||||
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), nxtiv, ALG_AES_IV_LEN);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
afalg_ctx *actx;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ALG_WARN("NULL parameter passed to function %s(%d)\n", __FILE__,
|
||||
__LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
actx = (afalg_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
|
||||
if (actx == NULL || actx->init_done != MAGIC_INIT_NUM)
|
||||
return 1;
|
||||
|
||||
close(actx->sfd);
|
||||
close(actx->bfd);
|
||||
# ifdef ALG_ZERO_COPY
|
||||
close(actx->zc_pipe[0]);
|
||||
close(actx->zc_pipe[1]);
|
||||
# endif
|
||||
/* close efd in sync mode, async mode is closed in afalg_waitfd_cleanup() */
|
||||
if (actx->aio.mode == MODE_SYNC)
|
||||
close(actx->aio.efd);
|
||||
io_destroy(actx->aio.aio_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cbc_handles *get_cipher_handle(int nid)
|
||||
{
|
||||
switch (nid) {
|
||||
case NID_aes_128_cbc:
|
||||
return &cbc_handle[AES_CBC_128];
|
||||
case NID_aes_192_cbc:
|
||||
return &cbc_handle[AES_CBC_192];
|
||||
case NID_aes_256_cbc:
|
||||
return &cbc_handle[AES_CBC_256];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const EVP_CIPHER *afalg_aes_cbc(int nid)
|
||||
{
|
||||
cbc_handles *cipher_handle = get_cipher_handle(nid);
|
||||
|
||||
if (cipher_handle == NULL)
|
||||
return NULL;
|
||||
if (cipher_handle->_hidden == NULL
|
||||
&& ((cipher_handle->_hidden =
|
||||
EVP_CIPHER_meth_new(nid,
|
||||
AES_BLOCK_SIZE,
|
||||
cipher_handle->key_size)) == NULL
|
||||
|| !EVP_CIPHER_meth_set_iv_length(cipher_handle->_hidden,
|
||||
AES_IV_LEN)
|
||||
|| !EVP_CIPHER_meth_set_flags(cipher_handle->_hidden,
|
||||
EVP_CIPH_CBC_MODE |
|
||||
EVP_CIPH_FLAG_DEFAULT_ASN1)
|
||||
|| !EVP_CIPHER_meth_set_init(cipher_handle->_hidden,
|
||||
afalg_cipher_init)
|
||||
|| !EVP_CIPHER_meth_set_do_cipher(cipher_handle->_hidden,
|
||||
afalg_do_cipher)
|
||||
|| !EVP_CIPHER_meth_set_cleanup(cipher_handle->_hidden,
|
||||
afalg_cipher_cleanup)
|
||||
|| !EVP_CIPHER_meth_set_impl_ctx_size(cipher_handle->_hidden,
|
||||
sizeof(afalg_ctx)))) {
|
||||
EVP_CIPHER_meth_free(cipher_handle->_hidden);
|
||||
cipher_handle->_hidden= NULL;
|
||||
}
|
||||
return cipher_handle->_hidden;
|
||||
}
|
||||
|
||||
static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
|
||||
const int **nids, int nid)
|
||||
{
|
||||
int r = 1;
|
||||
|
||||
if (cipher == NULL) {
|
||||
*nids = afalg_cipher_nids;
|
||||
return OSSL_NELEM(afalg_cipher_nids);
|
||||
}
|
||||
|
||||
switch (nid) {
|
||||
case NID_aes_128_cbc:
|
||||
case NID_aes_192_cbc:
|
||||
case NID_aes_256_cbc:
|
||||
*cipher = afalg_aes_cbc(nid);
|
||||
break;
|
||||
default:
|
||||
*cipher = NULL;
|
||||
r = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int bind_afalg(ENGINE *e)
|
||||
{
|
||||
/* Ensure the afalg error handling is set up */
|
||||
unsigned short i;
|
||||
ERR_load_AFALG_strings();
|
||||
|
||||
if (!ENGINE_set_id(e, engine_afalg_id)
|
||||
|| !ENGINE_set_name(e, engine_afalg_name)
|
||||
|| !ENGINE_set_destroy_function(e, afalg_destroy)
|
||||
|| !ENGINE_set_init_function(e, afalg_init)
|
||||
|| !ENGINE_set_finish_function(e, afalg_finish)) {
|
||||
AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create _hidden_aes_xxx_cbc by calling afalg_aes_xxx_cbc
|
||||
* now, as bind_aflag can only be called by one thread at a
|
||||
* time.
|
||||
*/
|
||||
for (i = 0; i < OSSL_NELEM(afalg_cipher_nids); i++) {
|
||||
if (afalg_aes_cbc(afalg_cipher_nids[i]) == NULL) {
|
||||
AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ENGINE_set_ciphers(e, afalg_ciphers)) {
|
||||
AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int afalg_chk_platform(void)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
int kver[3] = { -1, -1, -1 };
|
||||
int sock;
|
||||
char *str;
|
||||
struct utsname ut;
|
||||
|
||||
ret = uname(&ut);
|
||||
if (ret != 0) {
|
||||
AFALGerr(AFALG_F_AFALG_CHK_PLATFORM,
|
||||
AFALG_R_FAILED_TO_GET_PLATFORM_INFO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
str = strtok(ut.release, ".");
|
||||
for (i = 0; i < 3 && str != NULL; i++) {
|
||||
kver[i] = atoi(str);
|
||||
str = strtok(NULL, ".");
|
||||
}
|
||||
|
||||
if (KERNEL_VERSION(kver[0], kver[1], kver[2])
|
||||
< KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2)) {
|
||||
ALG_ERR("ASYNC AFALG not supported this kernel(%d.%d.%d)\n",
|
||||
kver[0], kver[1], kver[2]);
|
||||
ALG_ERR("ASYNC AFALG requires kernel version %d.%d.%d or later\n",
|
||||
K_MAJ, K_MIN1, K_MIN2);
|
||||
AFALGerr(AFALG_F_AFALG_CHK_PLATFORM,
|
||||
AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test if we can actually create an AF_ALG socket */
|
||||
sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
|
||||
if (sock == -1) {
|
||||
AFALGerr(AFALG_F_AFALG_CHK_PLATFORM, AFALG_R_SOCKET_CREATE_FAILED);
|
||||
return 0;
|
||||
}
|
||||
close(sock);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ENGINE *engine_afalg(void)
|
||||
{
|
||||
ENGINE *ret = ENGINE_new();
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
if (!bind_afalg(ret)) {
|
||||
ENGINE_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void engine_load_afalg_int(void)
|
||||
{
|
||||
ENGINE *toadd;
|
||||
|
||||
if (!afalg_chk_platform())
|
||||
return;
|
||||
|
||||
toadd = engine_afalg();
|
||||
if (toadd == NULL)
|
||||
return;
|
||||
ERR_set_mark();
|
||||
ENGINE_add(toadd);
|
||||
/*
|
||||
* If the "add" worked, it gets a structural reference. So either way, we
|
||||
* release our just-created reference.
|
||||
*/
|
||||
ENGINE_free(toadd);
|
||||
/*
|
||||
* If the "add" didn't work, it was probably a conflict because it was
|
||||
* already added (eg. someone calling ENGINE_load_blah then calling
|
||||
* ENGINE_load_builtin_engines() perhaps).
|
||||
*/
|
||||
ERR_pop_to_mark();
|
||||
}
|
||||
|
||||
static int afalg_init(ENGINE *e)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int afalg_finish(ENGINE *e)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int free_cbc(void)
|
||||
{
|
||||
short unsigned int i;
|
||||
for (i = 0; i < OSSL_NELEM(afalg_cipher_nids); i++) {
|
||||
EVP_CIPHER_meth_free(cbc_handle[i]._hidden);
|
||||
cbc_handle[i]._hidden = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int afalg_destroy(ENGINE *e)
|
||||
{
|
||||
ERR_unload_AFALG_strings();
|
||||
free_cbc();
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* KERNEL VERSION */
|
||||
@@ -1,3 +0,0 @@
|
||||
# The INPUT HEADER is scanned for declarations
|
||||
# LIBNAME INPUT HEADER ERROR-TABLE FILE
|
||||
L AFALG e_afalg_err.h e_afalg_err.c
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OSSL_ENGINES_E_AFALG_H
|
||||
# define OSSL_ENGINES_E_AFALG_H
|
||||
|
||||
# if defined(__GNUC__) && __GNUC__ >= 4 && \
|
||||
(!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
|
||||
# pragma GCC diagnostic ignored "-Wvariadic-macros"
|
||||
# endif
|
||||
|
||||
# ifdef ALG_DEBUG
|
||||
# define ALG_DGB(x, ...) fprintf(stderr, "ALG_DBG: " x, __VA_ARGS__)
|
||||
# define ALG_INFO(x, ...) fprintf(stderr, "ALG_INFO: " x, __VA_ARGS__)
|
||||
# define ALG_WARN(x, ...) fprintf(stderr, "ALG_WARN: " x, __VA_ARGS__)
|
||||
# else
|
||||
# define ALG_DGB(x, ...)
|
||||
# define ALG_INFO(x, ...)
|
||||
# define ALG_WARN(x, ...)
|
||||
# endif
|
||||
|
||||
# define ALG_ERR(x, ...) fprintf(stderr, "ALG_ERR: " x, __VA_ARGS__)
|
||||
# define ALG_PERR(x, ...) \
|
||||
do { \
|
||||
fprintf(stderr, "ALG_PERR: " x, __VA_ARGS__); \
|
||||
perror(NULL); \
|
||||
} while(0)
|
||||
# define ALG_PWARN(x, ...) \
|
||||
do { \
|
||||
fprintf(stderr, "ALG_PERR: " x, __VA_ARGS__); \
|
||||
perror(NULL); \
|
||||
} while(0)
|
||||
|
||||
# ifndef AES_BLOCK_SIZE
|
||||
# define AES_BLOCK_SIZE 16
|
||||
# endif
|
||||
# define AES_KEY_SIZE_128 16
|
||||
# define AES_KEY_SIZE_192 24
|
||||
# define AES_KEY_SIZE_256 32
|
||||
# define AES_IV_LEN 16
|
||||
|
||||
# define MAX_INFLIGHTS 1
|
||||
|
||||
typedef enum {
|
||||
MODE_UNINIT = 0,
|
||||
MODE_SYNC,
|
||||
MODE_ASYNC
|
||||
} op_mode;
|
||||
|
||||
enum {
|
||||
AES_CBC_128 = 0,
|
||||
AES_CBC_192,
|
||||
AES_CBC_256
|
||||
};
|
||||
|
||||
struct cbc_cipher_handles {
|
||||
int key_size;
|
||||
EVP_CIPHER *_hidden;
|
||||
};
|
||||
|
||||
typedef struct cbc_cipher_handles cbc_handles;
|
||||
|
||||
struct afalg_aio_st {
|
||||
int efd;
|
||||
op_mode mode;
|
||||
aio_context_t aio_ctx;
|
||||
struct io_event events[MAX_INFLIGHTS];
|
||||
struct iocb cbt[MAX_INFLIGHTS];
|
||||
};
|
||||
typedef struct afalg_aio_st afalg_aio;
|
||||
|
||||
/*
|
||||
* MAGIC Number to identify correct initialisation
|
||||
* of afalg_ctx.
|
||||
*/
|
||||
# define MAGIC_INIT_NUM 0x1890671
|
||||
|
||||
struct afalg_ctx_st {
|
||||
int init_done;
|
||||
int sfd;
|
||||
int bfd;
|
||||
# ifdef ALG_ZERO_COPY
|
||||
int zc_pipe[2];
|
||||
# endif
|
||||
afalg_aio aio;
|
||||
};
|
||||
|
||||
typedef struct afalg_ctx_st afalg_ctx;
|
||||
#endif
|
||||
@@ -1,22 +0,0 @@
|
||||
# Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
#Reason codes
|
||||
AFALG_R_EVENTFD_FAILED:108:eventfd failed
|
||||
AFALG_R_FAILED_TO_GET_PLATFORM_INFO:111:failed to get platform info
|
||||
AFALG_R_INIT_FAILED:100:init failed
|
||||
AFALG_R_IO_SETUP_FAILED:105:io setup failed
|
||||
AFALG_R_KERNEL_DOES_NOT_SUPPORT_AFALG:101:kernel does not support afalg
|
||||
AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG:107:\
|
||||
kernel does not support async afalg
|
||||
AFALG_R_KERNEL_OP_FAILED:112:kernel op failed
|
||||
AFALG_R_MEM_ALLOC_FAILED:102:mem alloc failed
|
||||
AFALG_R_SOCKET_ACCEPT_FAILED:110:socket accept failed
|
||||
AFALG_R_SOCKET_BIND_FAILED:103:socket bind failed
|
||||
AFALG_R_SOCKET_CREATE_FAILED:109:socket create failed
|
||||
AFALG_R_SOCKET_OPERATION_FAILED:104:socket operation failed
|
||||
AFALG_R_SOCKET_SET_KEY_FAILED:106:socket set key failed
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include "e_afalg_err.h"
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static ERR_STRING_DATA AFALG_str_reasons[] = {
|
||||
{ERR_PACK(0, 0, AFALG_R_EVENTFD_FAILED), "eventfd failed"},
|
||||
{ERR_PACK(0, 0, AFALG_R_FAILED_TO_GET_PLATFORM_INFO),
|
||||
"failed to get platform info"},
|
||||
{ERR_PACK(0, 0, AFALG_R_INIT_FAILED), "init failed"},
|
||||
{ERR_PACK(0, 0, AFALG_R_IO_SETUP_FAILED), "io setup failed"},
|
||||
{ERR_PACK(0, 0, AFALG_R_KERNEL_DOES_NOT_SUPPORT_AFALG),
|
||||
"kernel does not support afalg"},
|
||||
{ERR_PACK(0, 0, AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG),
|
||||
"kernel does not support async afalg"},
|
||||
{ERR_PACK(0, 0, AFALG_R_KERNEL_OP_FAILED), "kernel op failed"},
|
||||
{ERR_PACK(0, 0, AFALG_R_MEM_ALLOC_FAILED), "mem alloc failed"},
|
||||
{ERR_PACK(0, 0, AFALG_R_SOCKET_ACCEPT_FAILED), "socket accept failed"},
|
||||
{ERR_PACK(0, 0, AFALG_R_SOCKET_BIND_FAILED), "socket bind failed"},
|
||||
{ERR_PACK(0, 0, AFALG_R_SOCKET_CREATE_FAILED), "socket create failed"},
|
||||
{ERR_PACK(0, 0, AFALG_R_SOCKET_OPERATION_FAILED),
|
||||
"socket operation failed"},
|
||||
{ERR_PACK(0, 0, AFALG_R_SOCKET_SET_KEY_FAILED), "socket set key failed"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int lib_code = 0;
|
||||
static int error_loaded = 0;
|
||||
|
||||
static int ERR_load_AFALG_strings(void)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
|
||||
if (!error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_load_strings(lib_code, AFALG_str_reasons);
|
||||
#endif
|
||||
error_loaded = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ERR_unload_AFALG_strings(void)
|
||||
{
|
||||
if (error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_unload_strings(lib_code, AFALG_str_reasons);
|
||||
#endif
|
||||
error_loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ERR_AFALG_error(int function, int reason, const char *file, int line)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
ERR_raise(lib_code, reason);
|
||||
ERR_set_debug(file, line, NULL);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OSSL_E_AFALG_ERR_H
|
||||
# define OSSL_E_AFALG_ERR_H
|
||||
# pragma once
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
|
||||
# define AFALGerr(f, r) ERR_AFALG_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
|
||||
|
||||
|
||||
/*
|
||||
* AFALG reason codes.
|
||||
*/
|
||||
# define AFALG_R_EVENTFD_FAILED 108
|
||||
# define AFALG_R_FAILED_TO_GET_PLATFORM_INFO 111
|
||||
# define AFALG_R_INIT_FAILED 100
|
||||
# define AFALG_R_IO_SETUP_FAILED 105
|
||||
# define AFALG_R_KERNEL_DOES_NOT_SUPPORT_AFALG 101
|
||||
# define AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG 107
|
||||
# define AFALG_R_KERNEL_OP_FAILED 112
|
||||
# define AFALG_R_MEM_ALLOC_FAILED 102
|
||||
# define AFALG_R_SOCKET_ACCEPT_FAILED 110
|
||||
# define AFALG_R_SOCKET_BIND_FAILED 103
|
||||
# define AFALG_R_SOCKET_CREATE_FAILED 109
|
||||
# define AFALG_R_SOCKET_OPERATION_FAILED 104
|
||||
# define AFALG_R_SOCKET_SET_KEY_FAILED 106
|
||||
|
||||
#endif
|
||||
1910
engines/e_capi.c
1910
engines/e_capi.c
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
# The INPUT HEADER is scanned for declarations
|
||||
# LIBNAME INPUT HEADER ERROR-TABLE FILE
|
||||
L CAPI e_capi_err.h e_capi_err.c
|
||||
@@ -1,40 +0,0 @@
|
||||
# Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
#Reason codes
|
||||
CAPI_R_CANT_CREATE_HASH_OBJECT:100:can't create hash object
|
||||
CAPI_R_CANT_FIND_CAPI_CONTEXT:101:can't find capi context
|
||||
CAPI_R_CANT_GET_KEY:102:can't get key
|
||||
CAPI_R_CANT_SET_HASH_VALUE:103:can't set hash value
|
||||
CAPI_R_CRYPTACQUIRECONTEXT_ERROR:104:cryptacquirecontext error
|
||||
CAPI_R_CRYPTENUMPROVIDERS_ERROR:105:cryptenumproviders error
|
||||
CAPI_R_DECRYPT_ERROR:106:decrypt error
|
||||
CAPI_R_ENGINE_NOT_INITIALIZED:107:engine not initialized
|
||||
CAPI_R_ENUMCONTAINERS_ERROR:108:enumcontainers error
|
||||
CAPI_R_ERROR_ADDING_CERT:109:error adding cert
|
||||
CAPI_R_ERROR_CREATING_STORE:110:error creating store
|
||||
CAPI_R_ERROR_GETTING_FRIENDLY_NAME:111:error getting friendly name
|
||||
CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO:112:error getting key provider info
|
||||
CAPI_R_ERROR_OPENING_STORE:113:error opening store
|
||||
CAPI_R_ERROR_SIGNING_HASH:114:error signing hash
|
||||
CAPI_R_FILE_OPEN_ERROR:115:file open error
|
||||
CAPI_R_FUNCTION_NOT_SUPPORTED:116:function not supported
|
||||
CAPI_R_GETUSERKEY_ERROR:117:getuserkey error
|
||||
CAPI_R_INVALID_DIGEST_LENGTH:118:invalid digest length
|
||||
CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER:119:\
|
||||
invalid dsa public key blob magic number
|
||||
CAPI_R_INVALID_LOOKUP_METHOD:120:invalid lookup method
|
||||
CAPI_R_INVALID_PUBLIC_KEY_BLOB:121:invalid public key blob
|
||||
CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER:122:\
|
||||
invalid rsa public key blob magic number
|
||||
CAPI_R_PUBKEY_EXPORT_ERROR:123:pubkey export error
|
||||
CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR:124:pubkey export length error
|
||||
CAPI_R_UNKNOWN_COMMAND:125:unknown command
|
||||
CAPI_R_UNSUPPORTED_ALGORITHM_NID:126:unsupported algorithm nid
|
||||
CAPI_R_UNSUPPORTED_PADDING:127:unsupported padding
|
||||
CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM:128:unsupported public key algorithm
|
||||
CAPI_R_WIN32_ERROR:129:win32 error
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include "e_capi_err.h"
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static ERR_STRING_DATA CAPI_str_reasons[] = {
|
||||
{ERR_PACK(0, 0, CAPI_R_CANT_CREATE_HASH_OBJECT), "can't create hash object"},
|
||||
{ERR_PACK(0, 0, CAPI_R_CANT_FIND_CAPI_CONTEXT), "can't find capi context"},
|
||||
{ERR_PACK(0, 0, CAPI_R_CANT_GET_KEY), "can't get key"},
|
||||
{ERR_PACK(0, 0, CAPI_R_CANT_SET_HASH_VALUE), "can't set hash value"},
|
||||
{ERR_PACK(0, 0, CAPI_R_CRYPTACQUIRECONTEXT_ERROR),
|
||||
"cryptacquirecontext error"},
|
||||
{ERR_PACK(0, 0, CAPI_R_CRYPTENUMPROVIDERS_ERROR),
|
||||
"cryptenumproviders error"},
|
||||
{ERR_PACK(0, 0, CAPI_R_DECRYPT_ERROR), "decrypt error"},
|
||||
{ERR_PACK(0, 0, CAPI_R_ENGINE_NOT_INITIALIZED), "engine not initialized"},
|
||||
{ERR_PACK(0, 0, CAPI_R_ENUMCONTAINERS_ERROR), "enumcontainers error"},
|
||||
{ERR_PACK(0, 0, CAPI_R_ERROR_ADDING_CERT), "error adding cert"},
|
||||
{ERR_PACK(0, 0, CAPI_R_ERROR_CREATING_STORE), "error creating store"},
|
||||
{ERR_PACK(0, 0, CAPI_R_ERROR_GETTING_FRIENDLY_NAME),
|
||||
"error getting friendly name"},
|
||||
{ERR_PACK(0, 0, CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO),
|
||||
"error getting key provider info"},
|
||||
{ERR_PACK(0, 0, CAPI_R_ERROR_OPENING_STORE), "error opening store"},
|
||||
{ERR_PACK(0, 0, CAPI_R_ERROR_SIGNING_HASH), "error signing hash"},
|
||||
{ERR_PACK(0, 0, CAPI_R_FILE_OPEN_ERROR), "file open error"},
|
||||
{ERR_PACK(0, 0, CAPI_R_FUNCTION_NOT_SUPPORTED), "function not supported"},
|
||||
{ERR_PACK(0, 0, CAPI_R_GETUSERKEY_ERROR), "getuserkey error"},
|
||||
{ERR_PACK(0, 0, CAPI_R_INVALID_DIGEST_LENGTH), "invalid digest length"},
|
||||
{ERR_PACK(0, 0, CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER),
|
||||
"invalid dsa public key blob magic number"},
|
||||
{ERR_PACK(0, 0, CAPI_R_INVALID_LOOKUP_METHOD), "invalid lookup method"},
|
||||
{ERR_PACK(0, 0, CAPI_R_INVALID_PUBLIC_KEY_BLOB), "invalid public key blob"},
|
||||
{ERR_PACK(0, 0, CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER),
|
||||
"invalid rsa public key blob magic number"},
|
||||
{ERR_PACK(0, 0, CAPI_R_PUBKEY_EXPORT_ERROR), "pubkey export error"},
|
||||
{ERR_PACK(0, 0, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR),
|
||||
"pubkey export length error"},
|
||||
{ERR_PACK(0, 0, CAPI_R_UNKNOWN_COMMAND), "unknown command"},
|
||||
{ERR_PACK(0, 0, CAPI_R_UNSUPPORTED_ALGORITHM_NID),
|
||||
"unsupported algorithm nid"},
|
||||
{ERR_PACK(0, 0, CAPI_R_UNSUPPORTED_PADDING), "unsupported padding"},
|
||||
{ERR_PACK(0, 0, CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM),
|
||||
"unsupported public key algorithm"},
|
||||
{ERR_PACK(0, 0, CAPI_R_WIN32_ERROR), "win32 error"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int lib_code = 0;
|
||||
static int error_loaded = 0;
|
||||
|
||||
static int ERR_load_CAPI_strings(void)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
|
||||
if (!error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_load_strings(lib_code, CAPI_str_reasons);
|
||||
#endif
|
||||
error_loaded = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ERR_unload_CAPI_strings(void)
|
||||
{
|
||||
if (error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_unload_strings(lib_code, CAPI_str_reasons);
|
||||
#endif
|
||||
error_loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ERR_CAPI_error(int function, int reason, const char *file, int line)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
ERR_raise(lib_code, reason);
|
||||
ERR_set_debug(file, line, NULL);
|
||||
}
|
||||
|
||||
static int ERR_CAPI_lib(void)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
return lib_code;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OSSL_E_CAPI_ERR_H
|
||||
# define OSSL_E_CAPI_ERR_H
|
||||
# pragma once
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
|
||||
# define CAPIerr(f, r) ERR_CAPI_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
|
||||
# define ERR_R_CAPI_LIB ERR_CAPI_lib()
|
||||
|
||||
|
||||
/*
|
||||
* CAPI reason codes.
|
||||
*/
|
||||
# define CAPI_R_CANT_CREATE_HASH_OBJECT 100
|
||||
# define CAPI_R_CANT_FIND_CAPI_CONTEXT 101
|
||||
# define CAPI_R_CANT_GET_KEY 102
|
||||
# define CAPI_R_CANT_SET_HASH_VALUE 103
|
||||
# define CAPI_R_CRYPTACQUIRECONTEXT_ERROR 104
|
||||
# define CAPI_R_CRYPTENUMPROVIDERS_ERROR 105
|
||||
# define CAPI_R_DECRYPT_ERROR 106
|
||||
# define CAPI_R_ENGINE_NOT_INITIALIZED 107
|
||||
# define CAPI_R_ENUMCONTAINERS_ERROR 108
|
||||
# define CAPI_R_ERROR_ADDING_CERT 109
|
||||
# define CAPI_R_ERROR_CREATING_STORE 110
|
||||
# define CAPI_R_ERROR_GETTING_FRIENDLY_NAME 111
|
||||
# define CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO 112
|
||||
# define CAPI_R_ERROR_OPENING_STORE 113
|
||||
# define CAPI_R_ERROR_SIGNING_HASH 114
|
||||
# define CAPI_R_FILE_OPEN_ERROR 115
|
||||
# define CAPI_R_FUNCTION_NOT_SUPPORTED 116
|
||||
# define CAPI_R_GETUSERKEY_ERROR 117
|
||||
# define CAPI_R_INVALID_DIGEST_LENGTH 118
|
||||
# define CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER 119
|
||||
# define CAPI_R_INVALID_LOOKUP_METHOD 120
|
||||
# define CAPI_R_INVALID_PUBLIC_KEY_BLOB 121
|
||||
# define CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER 122
|
||||
# define CAPI_R_PUBKEY_EXPORT_ERROR 123
|
||||
# define CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR 124
|
||||
# define CAPI_R_UNKNOWN_COMMAND 125
|
||||
# define CAPI_R_UNSUPPORTED_ALGORITHM_NID 126
|
||||
# define CAPI_R_UNSUPPORTED_PADDING 127
|
||||
# define CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM 128
|
||||
# define CAPI_R_WIN32_ERROR 129
|
||||
|
||||
#endif
|
||||
@@ -1,994 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* We need to use some engine deprecated APIs */
|
||||
#define OPENSSL_SUPPRESS_DEPRECATED
|
||||
|
||||
/*
|
||||
* SHA-1 low level APIs are deprecated for public use, but still ok for
|
||||
* internal use. Note, that due to symbols not being exported, only the
|
||||
* #defines and structures can be accessed, in this case SHA_CBLOCK and
|
||||
* sizeof(SHA_CTX).
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/async.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/modes.h>
|
||||
|
||||
#if defined(OPENSSL_SYS_UNIX) && defined(OPENSSL_THREADS)
|
||||
# undef ASYNC_POSIX
|
||||
# define ASYNC_POSIX
|
||||
# include <unistd.h>
|
||||
#elif defined(_WIN32)
|
||||
# undef ASYNC_WIN
|
||||
# define ASYNC_WIN
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
#include "e_dasync_err.c"
|
||||
/* clang-format on */
|
||||
|
||||
/* Engine Id and Name */
|
||||
static const char *engine_dasync_id = "dasync";
|
||||
static const char *engine_dasync_name = "Dummy Async engine support";
|
||||
|
||||
|
||||
/* Engine Lifetime functions */
|
||||
static int dasync_destroy(ENGINE *e);
|
||||
static int dasync_init(ENGINE *e);
|
||||
static int dasync_finish(ENGINE *e);
|
||||
void engine_load_dasync_int(void);
|
||||
|
||||
|
||||
/* Set up digests. Just SHA1 for now */
|
||||
static int dasync_digests(ENGINE *e, const EVP_MD **digest,
|
||||
const int **nids, int nid);
|
||||
|
||||
static void dummy_pause_job(void);
|
||||
|
||||
/* SHA1 */
|
||||
static int dasync_sha1_init(EVP_MD_CTX *ctx);
|
||||
static int dasync_sha1_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count);
|
||||
static int dasync_sha1_final(EVP_MD_CTX *ctx, unsigned char *md);
|
||||
|
||||
/*
|
||||
* Holds the EVP_MD object for sha1 in this engine. Set up once only during
|
||||
* engine bind and can then be reused many times.
|
||||
*/
|
||||
static EVP_MD *_hidden_sha1_md = NULL;
|
||||
static const EVP_MD *dasync_sha1(void)
|
||||
{
|
||||
return _hidden_sha1_md;
|
||||
}
|
||||
static void destroy_digests(void)
|
||||
{
|
||||
EVP_MD_meth_free(_hidden_sha1_md);
|
||||
_hidden_sha1_md = NULL;
|
||||
}
|
||||
|
||||
static int dasync_digest_nids(const int **nids)
|
||||
{
|
||||
static int digest_nids[2] = { 0, 0 };
|
||||
static int pos = 0;
|
||||
static int init = 0;
|
||||
|
||||
if (!init) {
|
||||
const EVP_MD *md;
|
||||
if ((md = dasync_sha1()) != NULL)
|
||||
digest_nids[pos++] = EVP_MD_get_type(md);
|
||||
digest_nids[pos] = 0;
|
||||
init = 1;
|
||||
}
|
||||
*nids = digest_nids;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* RSA */
|
||||
static int dasync_pkey(ENGINE *e, EVP_PKEY_METHOD **pmeth,
|
||||
const int **pnids, int nid);
|
||||
|
||||
static int dasync_rsa_init(EVP_PKEY_CTX *ctx);
|
||||
static void dasync_rsa_cleanup(EVP_PKEY_CTX *ctx);
|
||||
static int dasync_rsa_paramgen_init(EVP_PKEY_CTX *ctx);
|
||||
static int dasync_rsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
|
||||
static int dasync_rsa_keygen_init(EVP_PKEY_CTX *ctx);
|
||||
static int dasync_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
|
||||
static int dasync_rsa_encrypt_init(EVP_PKEY_CTX *ctx);
|
||||
static int dasync_rsa_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
|
||||
size_t *outlen, const unsigned char *in,
|
||||
size_t inlen);
|
||||
static int dasync_rsa_decrypt_init(EVP_PKEY_CTX *ctx);
|
||||
static int dasync_rsa_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
|
||||
size_t *outlen, const unsigned char *in,
|
||||
size_t inlen);
|
||||
static int dasync_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
|
||||
static int dasync_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
|
||||
const char *value);
|
||||
|
||||
static EVP_PKEY_METHOD *dasync_rsa;
|
||||
static const EVP_PKEY_METHOD *dasync_rsa_orig;
|
||||
|
||||
/* AES */
|
||||
|
||||
static int dasync_aes128_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
|
||||
void *ptr);
|
||||
static int dasync_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc);
|
||||
static int dasync_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl);
|
||||
static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx);
|
||||
|
||||
static int dasync_aes256_ctr_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
|
||||
void *ptr);
|
||||
static int dasync_aes256_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc);
|
||||
static int dasync_aes256_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl);
|
||||
static int dasync_aes256_ctr_cleanup(EVP_CIPHER_CTX *ctx);
|
||||
|
||||
static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
|
||||
int arg, void *ptr);
|
||||
static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int enc);
|
||||
static int dasync_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx,
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
size_t inl);
|
||||
static int dasync_aes128_cbc_hmac_sha1_cleanup(EVP_CIPHER_CTX *ctx);
|
||||
|
||||
struct dasync_pipeline_ctx {
|
||||
void *inner_cipher_data;
|
||||
unsigned int numpipes;
|
||||
unsigned char **inbufs;
|
||||
unsigned char **outbufs;
|
||||
size_t *lens;
|
||||
unsigned char tlsaad[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN];
|
||||
unsigned int aadctr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Holds the EVP_CIPHER object for aes_128_cbc in this engine. Set up once only
|
||||
* during engine bind and can then be reused many times.
|
||||
*/
|
||||
static EVP_CIPHER *_hidden_aes_128_cbc = NULL;
|
||||
static const EVP_CIPHER *dasync_aes_128_cbc(void)
|
||||
{
|
||||
return _hidden_aes_128_cbc;
|
||||
}
|
||||
|
||||
static EVP_CIPHER *_hidden_aes_256_ctr = NULL;
|
||||
static const EVP_CIPHER *dasync_aes_256_ctr(void)
|
||||
{
|
||||
return _hidden_aes_256_ctr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Holds the EVP_CIPHER object for aes_128_cbc_hmac_sha1 in this engine. Set up
|
||||
* once only during engine bind and can then be reused many times.
|
||||
*
|
||||
* This 'stitched' cipher depends on the EVP_aes_128_cbc_hmac_sha1() cipher,
|
||||
* which is implemented only if the AES-NI instruction set extension is available
|
||||
* (see OPENSSL_IA32CAP(3)). If that's not the case, then this cipher will not
|
||||
* be available either.
|
||||
*
|
||||
* Note: Since it is a legacy mac-then-encrypt cipher, modern TLS peers (which
|
||||
* negotiate the encrypt-then-mac extension) won't negotiate it anyway.
|
||||
*/
|
||||
static EVP_CIPHER *_hidden_aes_128_cbc_hmac_sha1 = NULL;
|
||||
static const EVP_CIPHER *dasync_aes_128_cbc_hmac_sha1(void)
|
||||
{
|
||||
return _hidden_aes_128_cbc_hmac_sha1;
|
||||
}
|
||||
|
||||
static void destroy_ciphers(void)
|
||||
{
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_cbc);
|
||||
EVP_CIPHER_meth_free(_hidden_aes_256_ctr);
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1);
|
||||
_hidden_aes_128_cbc = NULL;
|
||||
_hidden_aes_256_ctr = NULL;
|
||||
_hidden_aes_128_cbc_hmac_sha1 = NULL;
|
||||
}
|
||||
|
||||
static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
|
||||
const int **nids, int nid);
|
||||
|
||||
static int dasync_cipher_nids[] = {
|
||||
NID_aes_128_cbc,
|
||||
NID_aes_256_ctr,
|
||||
NID_aes_128_cbc_hmac_sha1,
|
||||
0
|
||||
};
|
||||
|
||||
static int bind_dasync(ENGINE *e)
|
||||
{
|
||||
/* Setup RSA */
|
||||
if ((dasync_rsa_orig = EVP_PKEY_meth_find(EVP_PKEY_RSA)) == NULL
|
||||
|| (dasync_rsa = EVP_PKEY_meth_new(EVP_PKEY_RSA,
|
||||
EVP_PKEY_FLAG_AUTOARGLEN)) == NULL)
|
||||
return 0;
|
||||
EVP_PKEY_meth_set_init(dasync_rsa, dasync_rsa_init);
|
||||
EVP_PKEY_meth_set_cleanup(dasync_rsa, dasync_rsa_cleanup);
|
||||
EVP_PKEY_meth_set_paramgen(dasync_rsa, dasync_rsa_paramgen_init,
|
||||
dasync_rsa_paramgen);
|
||||
EVP_PKEY_meth_set_keygen(dasync_rsa, dasync_rsa_keygen_init,
|
||||
dasync_rsa_keygen);
|
||||
EVP_PKEY_meth_set_encrypt(dasync_rsa, dasync_rsa_encrypt_init,
|
||||
dasync_rsa_encrypt);
|
||||
EVP_PKEY_meth_set_decrypt(dasync_rsa, dasync_rsa_decrypt_init,
|
||||
dasync_rsa_decrypt);
|
||||
EVP_PKEY_meth_set_ctrl(dasync_rsa, dasync_rsa_ctrl,
|
||||
dasync_rsa_ctrl_str);
|
||||
|
||||
/* Ensure the dasync error handling is set up */
|
||||
ERR_load_DASYNC_strings();
|
||||
|
||||
if (!ENGINE_set_id(e, engine_dasync_id)
|
||||
|| !ENGINE_set_name(e, engine_dasync_name)
|
||||
|| !ENGINE_set_pkey_meths(e, dasync_pkey)
|
||||
|| !ENGINE_set_digests(e, dasync_digests)
|
||||
|| !ENGINE_set_ciphers(e, dasync_ciphers)
|
||||
|| !ENGINE_set_destroy_function(e, dasync_destroy)
|
||||
|| !ENGINE_set_init_function(e, dasync_init)
|
||||
|| !ENGINE_set_finish_function(e, dasync_finish)) {
|
||||
DASYNCerr(DASYNC_F_BIND_DASYNC, DASYNC_R_INIT_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the EVP_CIPHER and EVP_MD objects for the ciphers/digests
|
||||
* supplied by this engine
|
||||
*/
|
||||
_hidden_sha1_md = EVP_MD_meth_new(NID_sha1, NID_sha1WithRSAEncryption);
|
||||
if (_hidden_sha1_md == NULL
|
||||
|| !EVP_MD_meth_set_result_size(_hidden_sha1_md, SHA_DIGEST_LENGTH)
|
||||
|| !EVP_MD_meth_set_input_blocksize(_hidden_sha1_md, SHA_CBLOCK)
|
||||
|| !EVP_MD_meth_set_app_datasize(_hidden_sha1_md,
|
||||
sizeof(EVP_MD *) + sizeof(SHA_CTX))
|
||||
|| !EVP_MD_meth_set_flags(_hidden_sha1_md, EVP_MD_FLAG_DIGALGID_ABSENT)
|
||||
|| !EVP_MD_meth_set_init(_hidden_sha1_md, dasync_sha1_init)
|
||||
|| !EVP_MD_meth_set_update(_hidden_sha1_md, dasync_sha1_update)
|
||||
|| !EVP_MD_meth_set_final(_hidden_sha1_md, dasync_sha1_final)) {
|
||||
EVP_MD_meth_free(_hidden_sha1_md);
|
||||
_hidden_sha1_md = NULL;
|
||||
}
|
||||
|
||||
_hidden_aes_128_cbc = EVP_CIPHER_meth_new(NID_aes_128_cbc,
|
||||
16 /* block size */,
|
||||
16 /* key len */);
|
||||
if (_hidden_aes_128_cbc == NULL
|
||||
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc,16)
|
||||
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc,
|
||||
EVP_CIPH_FLAG_DEFAULT_ASN1
|
||||
| EVP_CIPH_CBC_MODE
|
||||
| EVP_CIPH_FLAG_PIPELINE
|
||||
| EVP_CIPH_CUSTOM_COPY)
|
||||
|| !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc,
|
||||
dasync_aes128_init_key)
|
||||
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc,
|
||||
dasync_aes128_cbc_cipher)
|
||||
|| !EVP_CIPHER_meth_set_cleanup(_hidden_aes_128_cbc,
|
||||
dasync_aes128_cbc_cleanup)
|
||||
|| !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc,
|
||||
dasync_aes128_cbc_ctrl)
|
||||
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc,
|
||||
sizeof(struct dasync_pipeline_ctx))) {
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_cbc);
|
||||
_hidden_aes_128_cbc = NULL;
|
||||
}
|
||||
|
||||
_hidden_aes_256_ctr = EVP_CIPHER_meth_new(NID_aes_256_ctr,
|
||||
1 /* block size */,
|
||||
32 /* key len */);
|
||||
if (_hidden_aes_256_ctr == NULL
|
||||
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_256_ctr,16)
|
||||
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_256_ctr,
|
||||
EVP_CIPH_FLAG_DEFAULT_ASN1
|
||||
| EVP_CIPH_CTR_MODE
|
||||
| EVP_CIPH_FLAG_PIPELINE
|
||||
| EVP_CIPH_CUSTOM_COPY)
|
||||
|| !EVP_CIPHER_meth_set_init(_hidden_aes_256_ctr,
|
||||
dasync_aes256_init_key)
|
||||
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_256_ctr,
|
||||
dasync_aes256_ctr_cipher)
|
||||
|| !EVP_CIPHER_meth_set_cleanup(_hidden_aes_256_ctr,
|
||||
dasync_aes256_ctr_cleanup)
|
||||
|| !EVP_CIPHER_meth_set_ctrl(_hidden_aes_256_ctr,
|
||||
dasync_aes256_ctr_ctrl)
|
||||
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_256_ctr,
|
||||
sizeof(struct dasync_pipeline_ctx))) {
|
||||
EVP_CIPHER_meth_free(_hidden_aes_256_ctr);
|
||||
_hidden_aes_256_ctr = NULL;
|
||||
}
|
||||
|
||||
_hidden_aes_128_cbc_hmac_sha1 = EVP_CIPHER_meth_new(
|
||||
NID_aes_128_cbc_hmac_sha1,
|
||||
16 /* block size */,
|
||||
16 /* key len */);
|
||||
if (_hidden_aes_128_cbc_hmac_sha1 == NULL
|
||||
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc_hmac_sha1,16)
|
||||
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc_hmac_sha1,
|
||||
EVP_CIPH_CBC_MODE
|
||||
| EVP_CIPH_FLAG_DEFAULT_ASN1
|
||||
| EVP_CIPH_FLAG_AEAD_CIPHER
|
||||
| EVP_CIPH_FLAG_PIPELINE
|
||||
| EVP_CIPH_CUSTOM_COPY)
|
||||
|| !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc_hmac_sha1,
|
||||
dasync_aes128_cbc_hmac_sha1_init_key)
|
||||
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc_hmac_sha1,
|
||||
dasync_aes128_cbc_hmac_sha1_cipher)
|
||||
|| !EVP_CIPHER_meth_set_cleanup(_hidden_aes_128_cbc_hmac_sha1,
|
||||
dasync_aes128_cbc_hmac_sha1_cleanup)
|
||||
|| !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc_hmac_sha1,
|
||||
dasync_aes128_cbc_hmac_sha1_ctrl)
|
||||
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc_hmac_sha1,
|
||||
sizeof(struct dasync_pipeline_ctx))) {
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1);
|
||||
_hidden_aes_128_cbc_hmac_sha1 = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void destroy_pkey(void)
|
||||
{
|
||||
/*
|
||||
* We don't actually need to free the dasync_rsa method since this is
|
||||
* automatically freed for us by libcrypto.
|
||||
*/
|
||||
dasync_rsa_orig = NULL;
|
||||
dasync_rsa = NULL;
|
||||
}
|
||||
|
||||
static ENGINE *engine_dasync(void)
|
||||
{
|
||||
ENGINE *ret = ENGINE_new();
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!bind_dasync(ret)) {
|
||||
ENGINE_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void engine_load_dasync_int(void)
|
||||
{
|
||||
ENGINE *toadd = engine_dasync();
|
||||
if (!toadd)
|
||||
return;
|
||||
ERR_set_mark();
|
||||
ENGINE_add(toadd);
|
||||
/*
|
||||
* If the "add" worked, it gets a structural reference. So either way, we
|
||||
* release our just-created reference.
|
||||
*/
|
||||
ENGINE_free(toadd);
|
||||
/*
|
||||
* If the "add" didn't work, it was probably a conflict because it was
|
||||
* already added (eg. someone calling ENGINE_load_blah then calling
|
||||
* ENGINE_load_builtin_engines() perhaps).
|
||||
*/
|
||||
ERR_pop_to_mark();
|
||||
}
|
||||
|
||||
static int dasync_init(ENGINE *e)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int dasync_finish(ENGINE *e)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int dasync_destroy(ENGINE *e)
|
||||
{
|
||||
destroy_digests();
|
||||
destroy_ciphers();
|
||||
destroy_pkey();
|
||||
ERR_unload_DASYNC_strings();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dasync_pkey(ENGINE *e, EVP_PKEY_METHOD **pmeth,
|
||||
const int **pnids, int nid)
|
||||
{
|
||||
static const int rnid = EVP_PKEY_RSA;
|
||||
|
||||
if (pmeth == NULL) {
|
||||
*pnids = &rnid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nid == EVP_PKEY_RSA) {
|
||||
*pmeth = dasync_rsa;
|
||||
return 1;
|
||||
}
|
||||
|
||||
*pmeth = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dasync_digests(ENGINE *e, const EVP_MD **digest,
|
||||
const int **nids, int nid)
|
||||
{
|
||||
int ok = 1;
|
||||
if (!digest) {
|
||||
/* We are returning a list of supported nids */
|
||||
return dasync_digest_nids(nids);
|
||||
}
|
||||
/* We are being asked for a specific digest */
|
||||
switch (nid) {
|
||||
case NID_sha1:
|
||||
*digest = dasync_sha1();
|
||||
break;
|
||||
default:
|
||||
ok = 0;
|
||||
*digest = NULL;
|
||||
break;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
|
||||
const int **nids, int nid)
|
||||
{
|
||||
int ok = 1;
|
||||
if (cipher == NULL) {
|
||||
/* We are returning a list of supported nids */
|
||||
*nids = dasync_cipher_nids;
|
||||
return (sizeof(dasync_cipher_nids) -
|
||||
1) / sizeof(dasync_cipher_nids[0]);
|
||||
}
|
||||
/* We are being asked for a specific cipher */
|
||||
switch (nid) {
|
||||
case NID_aes_128_cbc:
|
||||
*cipher = dasync_aes_128_cbc();
|
||||
break;
|
||||
case NID_aes_256_ctr:
|
||||
*cipher = dasync_aes_256_ctr();
|
||||
break;
|
||||
case NID_aes_128_cbc_hmac_sha1:
|
||||
*cipher = dasync_aes_128_cbc_hmac_sha1();
|
||||
break;
|
||||
default:
|
||||
ok = 0;
|
||||
*cipher = NULL;
|
||||
break;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void wait_cleanup(ASYNC_WAIT_CTX *ctx, const void *key,
|
||||
OSSL_ASYNC_FD readfd, void *pvwritefd)
|
||||
{
|
||||
OSSL_ASYNC_FD *pwritefd = (OSSL_ASYNC_FD *)pvwritefd;
|
||||
#if defined(ASYNC_WIN)
|
||||
CloseHandle(readfd);
|
||||
CloseHandle(*pwritefd);
|
||||
#elif defined(ASYNC_POSIX)
|
||||
close(readfd);
|
||||
close(*pwritefd);
|
||||
#endif
|
||||
OPENSSL_free(pwritefd);
|
||||
}
|
||||
|
||||
#define DUMMY_CHAR 'X'
|
||||
|
||||
static void dummy_pause_job(void) {
|
||||
ASYNC_JOB *job;
|
||||
ASYNC_WAIT_CTX *waitctx;
|
||||
ASYNC_callback_fn callback;
|
||||
void *callback_arg;
|
||||
OSSL_ASYNC_FD pipefds[2] = {0, 0};
|
||||
OSSL_ASYNC_FD *writefd;
|
||||
#if defined(ASYNC_WIN)
|
||||
DWORD numwritten, numread;
|
||||
char buf = DUMMY_CHAR;
|
||||
#elif defined(ASYNC_POSIX)
|
||||
char buf = DUMMY_CHAR;
|
||||
#endif
|
||||
|
||||
if ((job = ASYNC_get_current_job()) == NULL)
|
||||
return;
|
||||
|
||||
waitctx = ASYNC_get_wait_ctx(job);
|
||||
|
||||
if (ASYNC_WAIT_CTX_get_callback(waitctx, &callback, &callback_arg) && callback != NULL) {
|
||||
/*
|
||||
* In the Dummy async engine we are cheating. We call the callback that the job
|
||||
* is complete before the call to ASYNC_pause_job(). A real
|
||||
* async engine would only call the callback when the job was actually complete
|
||||
*/
|
||||
(*callback)(callback_arg);
|
||||
ASYNC_pause_job();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_dasync_id, &pipefds[0],
|
||||
(void **)&writefd)) {
|
||||
pipefds[1] = *writefd;
|
||||
} else {
|
||||
writefd = OPENSSL_malloc(sizeof(*writefd));
|
||||
if (writefd == NULL)
|
||||
return;
|
||||
#if defined(ASYNC_WIN)
|
||||
if (CreatePipe(&pipefds[0], &pipefds[1], NULL, 256) == 0) {
|
||||
OPENSSL_free(writefd);
|
||||
return;
|
||||
}
|
||||
#elif defined(ASYNC_POSIX)
|
||||
if (pipe(pipefds) != 0) {
|
||||
OPENSSL_free(writefd);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
*writefd = pipefds[1];
|
||||
|
||||
if (!ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_dasync_id, pipefds[0],
|
||||
writefd, wait_cleanup)) {
|
||||
wait_cleanup(waitctx, engine_dasync_id, pipefds[0], writefd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* In the Dummy async engine we are cheating. We signal that the job
|
||||
* is complete by waking it before the call to ASYNC_pause_job(). A real
|
||||
* async engine would only wake when the job was actually complete
|
||||
*/
|
||||
#if defined(ASYNC_WIN)
|
||||
WriteFile(pipefds[1], &buf, 1, &numwritten, NULL);
|
||||
#elif defined(ASYNC_POSIX)
|
||||
if (write(pipefds[1], &buf, 1) < 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Ignore errors - we carry on anyway */
|
||||
ASYNC_pause_job();
|
||||
|
||||
/* Clear the wake signal */
|
||||
#if defined(ASYNC_WIN)
|
||||
ReadFile(pipefds[0], &buf, 1, &numread, NULL);
|
||||
#elif defined(ASYNC_POSIX)
|
||||
if (read(pipefds[0], &buf, 1) < 0)
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA1 implementation. At the moment we just defer to the standard
|
||||
* implementation
|
||||
*/
|
||||
static int dasync_sha1_init(EVP_MD_CTX *ctx)
|
||||
{
|
||||
dummy_pause_job();
|
||||
|
||||
return EVP_MD_meth_get_init(EVP_sha1())(ctx);
|
||||
}
|
||||
|
||||
static int dasync_sha1_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count)
|
||||
{
|
||||
dummy_pause_job();
|
||||
|
||||
return EVP_MD_meth_get_update(EVP_sha1())(ctx, data, count);
|
||||
}
|
||||
|
||||
static int dasync_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
dummy_pause_job();
|
||||
|
||||
return EVP_MD_meth_get_final(EVP_sha1())(ctx, md);
|
||||
}
|
||||
|
||||
/* Cipher helper functions */
|
||||
|
||||
static int dasync_cipher_ctrl_helper(EVP_CIPHER_CTX *ctx, int type, int arg,
|
||||
void *ptr, int aeadcapable,
|
||||
const EVP_CIPHER *ciph)
|
||||
{
|
||||
int ret;
|
||||
struct dasync_pipeline_ctx *pipe_ctx =
|
||||
(struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
|
||||
|
||||
if (pipe_ctx == NULL)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case EVP_CTRL_COPY:
|
||||
{
|
||||
size_t sz = EVP_CIPHER_impl_ctx_size(ciph);
|
||||
void *inner_cipher_data = OPENSSL_malloc(sz);
|
||||
|
||||
if (inner_cipher_data == NULL)
|
||||
return -1;
|
||||
memcpy(inner_cipher_data, pipe_ctx->inner_cipher_data, sz);
|
||||
pipe_ctx->inner_cipher_data = inner_cipher_data;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS:
|
||||
pipe_ctx->numpipes = arg;
|
||||
pipe_ctx->outbufs = (unsigned char **)ptr;
|
||||
break;
|
||||
|
||||
case EVP_CTRL_SET_PIPELINE_INPUT_BUFS:
|
||||
pipe_ctx->numpipes = arg;
|
||||
pipe_ctx->inbufs = (unsigned char **)ptr;
|
||||
break;
|
||||
|
||||
case EVP_CTRL_SET_PIPELINE_INPUT_LENS:
|
||||
pipe_ctx->numpipes = arg;
|
||||
pipe_ctx->lens = (size_t *)ptr;
|
||||
break;
|
||||
|
||||
case EVP_CTRL_AEAD_SET_MAC_KEY:
|
||||
if (!aeadcapable)
|
||||
return -1;
|
||||
EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data);
|
||||
ret = EVP_CIPHER_meth_get_ctrl(EVP_aes_128_cbc_hmac_sha1())
|
||||
(ctx, type, arg, ptr);
|
||||
EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx);
|
||||
return ret;
|
||||
|
||||
case EVP_CTRL_AEAD_TLS1_AAD:
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
unsigned int len;
|
||||
|
||||
if (!aeadcapable || arg != EVP_AEAD_TLS1_AAD_LEN)
|
||||
return -1;
|
||||
|
||||
if (pipe_ctx->aadctr >= SSL_MAX_PIPELINES)
|
||||
return -1;
|
||||
|
||||
memcpy(pipe_ctx->tlsaad[pipe_ctx->aadctr], ptr,
|
||||
EVP_AEAD_TLS1_AAD_LEN);
|
||||
pipe_ctx->aadctr++;
|
||||
|
||||
len = p[arg - 2] << 8 | p[arg - 1];
|
||||
|
||||
if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
|
||||
if ((p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) {
|
||||
if (len < AES_BLOCK_SIZE)
|
||||
return 0;
|
||||
len -= AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
return ((len + SHA_DIGEST_LENGTH + AES_BLOCK_SIZE)
|
||||
& -AES_BLOCK_SIZE) - len;
|
||||
} else {
|
||||
return SHA_DIGEST_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dasync_cipher_init_key_helper(EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv, int enc,
|
||||
const EVP_CIPHER *cipher)
|
||||
{
|
||||
int ret;
|
||||
struct dasync_pipeline_ctx *pipe_ctx =
|
||||
(struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
|
||||
|
||||
if (pipe_ctx->inner_cipher_data == NULL
|
||||
&& EVP_CIPHER_impl_ctx_size(cipher) != 0) {
|
||||
pipe_ctx->inner_cipher_data = OPENSSL_zalloc(
|
||||
EVP_CIPHER_impl_ctx_size(cipher));
|
||||
if (pipe_ctx->inner_cipher_data == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
pipe_ctx->numpipes = 0;
|
||||
pipe_ctx->aadctr = 0;
|
||||
|
||||
EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data);
|
||||
ret = EVP_CIPHER_meth_get_init(cipher)(ctx, key, iv, enc);
|
||||
EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dasync_cipher_helper(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl,
|
||||
const EVP_CIPHER *cipher)
|
||||
{
|
||||
int ret = 1;
|
||||
unsigned int i, pipes;
|
||||
struct dasync_pipeline_ctx *pipe_ctx =
|
||||
(struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
|
||||
|
||||
pipes = pipe_ctx->numpipes;
|
||||
EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data);
|
||||
if (pipes == 0) {
|
||||
if (pipe_ctx->aadctr != 0) {
|
||||
if (pipe_ctx->aadctr != 1)
|
||||
return -1;
|
||||
EVP_CIPHER_meth_get_ctrl(cipher)
|
||||
(ctx, EVP_CTRL_AEAD_TLS1_AAD,
|
||||
EVP_AEAD_TLS1_AAD_LEN,
|
||||
pipe_ctx->tlsaad[0]);
|
||||
}
|
||||
ret = EVP_CIPHER_meth_get_do_cipher(cipher)
|
||||
(ctx, out, in, inl);
|
||||
} else {
|
||||
if (pipe_ctx->aadctr > 0 && pipe_ctx->aadctr != pipes)
|
||||
return -1;
|
||||
for (i = 0; i < pipes; i++) {
|
||||
if (pipe_ctx->aadctr > 0) {
|
||||
EVP_CIPHER_meth_get_ctrl(cipher)
|
||||
(ctx, EVP_CTRL_AEAD_TLS1_AAD,
|
||||
EVP_AEAD_TLS1_AAD_LEN,
|
||||
pipe_ctx->tlsaad[i]);
|
||||
}
|
||||
ret = ret && EVP_CIPHER_meth_get_do_cipher(cipher)
|
||||
(ctx, pipe_ctx->outbufs[i], pipe_ctx->inbufs[i],
|
||||
pipe_ctx->lens[i]);
|
||||
}
|
||||
pipe_ctx->numpipes = 0;
|
||||
}
|
||||
pipe_ctx->aadctr = 0;
|
||||
EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dasync_cipher_cleanup_helper(EVP_CIPHER_CTX *ctx,
|
||||
const EVP_CIPHER *cipher)
|
||||
{
|
||||
struct dasync_pipeline_ctx *pipe_ctx =
|
||||
(struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
|
||||
|
||||
OPENSSL_clear_free(pipe_ctx->inner_cipher_data,
|
||||
EVP_CIPHER_impl_ctx_size(cipher));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES128 CBC Implementation
|
||||
*/
|
||||
|
||||
static int dasync_aes128_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
|
||||
void *ptr)
|
||||
{
|
||||
return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 0, EVP_aes_128_cbc());
|
||||
}
|
||||
|
||||
static int dasync_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
return dasync_cipher_init_key_helper(ctx, key, iv, enc, EVP_aes_128_cbc());
|
||||
}
|
||||
|
||||
static int dasync_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
return dasync_cipher_helper(ctx, out, in, inl, EVP_aes_128_cbc());
|
||||
}
|
||||
|
||||
static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
return dasync_cipher_cleanup_helper(ctx, EVP_aes_128_cbc());
|
||||
}
|
||||
|
||||
static int dasync_aes256_ctr_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
|
||||
void *ptr)
|
||||
{
|
||||
return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 0, EVP_aes_256_ctr());
|
||||
}
|
||||
|
||||
static int dasync_aes256_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
return dasync_cipher_init_key_helper(ctx, key, iv, enc, EVP_aes_256_ctr());
|
||||
}
|
||||
|
||||
static int dasync_aes256_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
return dasync_cipher_helper(ctx, out, in, inl, EVP_aes_256_ctr());
|
||||
}
|
||||
|
||||
static int dasync_aes256_ctr_cleanup(EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
return dasync_cipher_cleanup_helper(ctx, EVP_aes_256_ctr());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AES128 CBC HMAC SHA1 Implementation
|
||||
*/
|
||||
|
||||
static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
|
||||
int arg, void *ptr)
|
||||
{
|
||||
return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 1, EVP_aes_128_cbc_hmac_sha1());
|
||||
}
|
||||
|
||||
static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int enc)
|
||||
{
|
||||
/*
|
||||
* We can safely assume that EVP_aes_128_cbc_hmac_sha1() != NULL,
|
||||
* see comment before the definition of dasync_aes_128_cbc_hmac_sha1().
|
||||
*/
|
||||
return dasync_cipher_init_key_helper(ctx, key, iv, enc,
|
||||
EVP_aes_128_cbc_hmac_sha1());
|
||||
}
|
||||
|
||||
static int dasync_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx,
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
size_t inl)
|
||||
{
|
||||
return dasync_cipher_helper(ctx, out, in, inl, EVP_aes_128_cbc_hmac_sha1());
|
||||
}
|
||||
|
||||
static int dasync_aes128_cbc_hmac_sha1_cleanup(EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
/*
|
||||
* We can safely assume that EVP_aes_128_cbc_hmac_sha1() != NULL,
|
||||
* see comment before the definition of dasync_aes_128_cbc_hmac_sha1().
|
||||
*/
|
||||
return dasync_cipher_cleanup_helper(ctx, EVP_aes_128_cbc_hmac_sha1());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RSA implementation
|
||||
*/
|
||||
static int dasync_rsa_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
static int (*pinit)(EVP_PKEY_CTX *ctx);
|
||||
|
||||
if (pinit == NULL)
|
||||
EVP_PKEY_meth_get_init(dasync_rsa_orig, &pinit);
|
||||
return pinit(ctx);
|
||||
}
|
||||
|
||||
static void dasync_rsa_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
static void (*pcleanup)(EVP_PKEY_CTX *ctx);
|
||||
|
||||
if (pcleanup == NULL)
|
||||
EVP_PKEY_meth_get_cleanup(dasync_rsa_orig, &pcleanup);
|
||||
pcleanup(ctx);
|
||||
}
|
||||
|
||||
static int dasync_rsa_paramgen_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
static int (*pparamgen_init)(EVP_PKEY_CTX *ctx);
|
||||
|
||||
if (pparamgen_init == NULL)
|
||||
EVP_PKEY_meth_get_paramgen(dasync_rsa_orig, &pparamgen_init, NULL);
|
||||
return pparamgen_init != NULL ? pparamgen_init(ctx) : 1;
|
||||
}
|
||||
|
||||
static int dasync_rsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
static int (*pparamgen)(EVP_PKEY_CTX *c, EVP_PKEY *pkey);
|
||||
|
||||
if (pparamgen == NULL)
|
||||
EVP_PKEY_meth_get_paramgen(dasync_rsa_orig, NULL, &pparamgen);
|
||||
return pparamgen != NULL ? pparamgen(ctx, pkey) : 1;
|
||||
}
|
||||
|
||||
static int dasync_rsa_keygen_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
static int (*pkeygen_init)(EVP_PKEY_CTX *ctx);
|
||||
|
||||
if (pkeygen_init == NULL)
|
||||
EVP_PKEY_meth_get_keygen(dasync_rsa_orig, &pkeygen_init, NULL);
|
||||
return pkeygen_init != NULL ? pkeygen_init(ctx) : 1;
|
||||
}
|
||||
|
||||
static int dasync_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
static int (*pkeygen)(EVP_PKEY_CTX *c, EVP_PKEY *pkey);
|
||||
|
||||
if (pkeygen == NULL)
|
||||
EVP_PKEY_meth_get_keygen(dasync_rsa_orig, NULL, &pkeygen);
|
||||
return pkeygen(ctx, pkey);
|
||||
}
|
||||
|
||||
static int dasync_rsa_encrypt_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
static int (*pencrypt_init)(EVP_PKEY_CTX *ctx);
|
||||
|
||||
if (pencrypt_init == NULL)
|
||||
EVP_PKEY_meth_get_encrypt(dasync_rsa_orig, &pencrypt_init, NULL);
|
||||
return pencrypt_init != NULL ? pencrypt_init(ctx) : 1;
|
||||
}
|
||||
|
||||
static int dasync_rsa_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
|
||||
size_t *outlen, const unsigned char *in,
|
||||
size_t inlen)
|
||||
{
|
||||
static int (*pencryptfn)(EVP_PKEY_CTX *ctx, unsigned char *out,
|
||||
size_t *outlen, const unsigned char *in,
|
||||
size_t inlen);
|
||||
|
||||
if (pencryptfn == NULL)
|
||||
EVP_PKEY_meth_get_encrypt(dasync_rsa_orig, NULL, &pencryptfn);
|
||||
return pencryptfn(ctx, out, outlen, in, inlen);
|
||||
}
|
||||
|
||||
static int dasync_rsa_decrypt_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
static int (*pdecrypt_init)(EVP_PKEY_CTX *ctx);
|
||||
|
||||
if (pdecrypt_init == NULL)
|
||||
EVP_PKEY_meth_get_decrypt(dasync_rsa_orig, &pdecrypt_init, NULL);
|
||||
return pdecrypt_init != NULL ? pdecrypt_init(ctx) : 1;
|
||||
}
|
||||
|
||||
static int dasync_rsa_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
|
||||
size_t *outlen, const unsigned char *in,
|
||||
size_t inlen)
|
||||
{
|
||||
static int (*pdecrypt)(EVP_PKEY_CTX *ctx, unsigned char *out,
|
||||
size_t *outlen, const unsigned char *in,
|
||||
size_t inlen);
|
||||
|
||||
if (pdecrypt == NULL)
|
||||
EVP_PKEY_meth_get_decrypt(dasync_rsa_orig, NULL, &pdecrypt);
|
||||
return pdecrypt(ctx, out, outlen, in, inlen);
|
||||
}
|
||||
|
||||
static int dasync_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
static int (*pctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
|
||||
|
||||
if (pctrl == NULL)
|
||||
EVP_PKEY_meth_get_ctrl(dasync_rsa_orig, &pctrl, NULL);
|
||||
return pctrl(ctx, type, p1, p2);
|
||||
}
|
||||
|
||||
static int dasync_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
|
||||
const char *value)
|
||||
{
|
||||
static int (*pctrl_str)(EVP_PKEY_CTX *ctx, const char *type,
|
||||
const char *value);
|
||||
|
||||
if (pctrl_str == NULL)
|
||||
EVP_PKEY_meth_get_ctrl(dasync_rsa_orig, NULL, &pctrl_str);
|
||||
return pctrl_str(ctx, type, value);
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
# The INPUT HEADER is scanned for declarations
|
||||
# LIBNAME INPUT HEADER ERROR-TABLE FILE
|
||||
L DASYNC e_dasync_err.h e_dasync_err.c
|
||||
@@ -1,9 +0,0 @@
|
||||
# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
#Reason codes
|
||||
DASYNC_R_INIT_FAILED:100:init failed
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include "e_dasync_err.h"
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static ERR_STRING_DATA DASYNC_str_reasons[] = {
|
||||
{ERR_PACK(0, 0, DASYNC_R_INIT_FAILED), "init failed"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int lib_code = 0;
|
||||
static int error_loaded = 0;
|
||||
|
||||
static int ERR_load_DASYNC_strings(void)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
|
||||
if (!error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_load_strings(lib_code, DASYNC_str_reasons);
|
||||
#endif
|
||||
error_loaded = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ERR_unload_DASYNC_strings(void)
|
||||
{
|
||||
if (error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_unload_strings(lib_code, DASYNC_str_reasons);
|
||||
#endif
|
||||
error_loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ERR_DASYNC_error(int function, int reason, const char *file, int line)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
ERR_raise(lib_code, reason);
|
||||
ERR_set_debug(file, line, NULL);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OSSL_E_DASYNC_ERR_H
|
||||
# define OSSL_E_DASYNC_ERR_H
|
||||
# pragma once
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
|
||||
# define DASYNCerr(f, r) ERR_DASYNC_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
|
||||
|
||||
|
||||
/*
|
||||
* DASYNC reason codes.
|
||||
*/
|
||||
# define DASYNC_R_INIT_FAILED 100
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
# The INPUT HEADER is scanned for declarations
|
||||
# LIBNAME INPUT HEADER ERROR-TABLE FILE
|
||||
L ATTIC e_loader_attic_err.h e_loader_attic_err.c
|
||||
@@ -1,21 +0,0 @@
|
||||
# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
#Reason codes
|
||||
ATTIC_R_AMBIGUOUS_CONTENT_TYPE:100:ambiguous content type
|
||||
ATTIC_R_BAD_PASSWORD_READ:101:bad password read
|
||||
ATTIC_R_ERROR_VERIFYING_PKCS12_MAC:102:error verifying pkcs12 mac
|
||||
ATTIC_R_INIT_FAILED:103:init failed
|
||||
ATTIC_R_PASSPHRASE_CALLBACK_ERROR:104:passphrase callback error
|
||||
ATTIC_R_PATH_MUST_BE_ABSOLUTE:105:path must be absolute
|
||||
ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:106:\
|
||||
search only supported for directories
|
||||
ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED:107:\
|
||||
ui process interrupted or cancelled
|
||||
ATTIC_R_UNSUPPORTED_CONTENT_TYPE:108:unsupported content type
|
||||
ATTIC_R_UNSUPPORTED_SEARCH_TYPE:109:unsupported search type
|
||||
ATTIC_R_URI_AUTHORITY_UNSUPPORTED:110:uri authority unsupported
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include "e_loader_attic_err.h"
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static ERR_STRING_DATA ATTIC_str_reasons[] = {
|
||||
{ERR_PACK(0, 0, ATTIC_R_AMBIGUOUS_CONTENT_TYPE), "ambiguous content type"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_BAD_PASSWORD_READ), "bad password read"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_ERROR_VERIFYING_PKCS12_MAC),
|
||||
"error verifying pkcs12 mac"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_INIT_FAILED), "init failed"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_PASSPHRASE_CALLBACK_ERROR),
|
||||
"passphrase callback error"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_PATH_MUST_BE_ABSOLUTE), "path must be absolute"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES),
|
||||
"search only supported for directories"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED),
|
||||
"ui process interrupted or cancelled"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_UNSUPPORTED_CONTENT_TYPE),
|
||||
"unsupported content type"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_UNSUPPORTED_SEARCH_TYPE),
|
||||
"unsupported search type"},
|
||||
{ERR_PACK(0, 0, ATTIC_R_URI_AUTHORITY_UNSUPPORTED),
|
||||
"uri authority unsupported"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int lib_code = 0;
|
||||
static int error_loaded = 0;
|
||||
|
||||
static int ERR_load_ATTIC_strings(void)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
|
||||
if (!error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_load_strings(lib_code, ATTIC_str_reasons);
|
||||
#endif
|
||||
error_loaded = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ERR_unload_ATTIC_strings(void)
|
||||
{
|
||||
if (error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_unload_strings(lib_code, ATTIC_str_reasons);
|
||||
#endif
|
||||
error_loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ERR_ATTIC_error(int function, int reason, const char *file, int line)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
ERR_raise(lib_code, reason);
|
||||
ERR_set_debug(file, line, NULL);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OSSL_E_LOADER_ATTIC_ERR_H
|
||||
# define OSSL_E_LOADER_ATTIC_ERR_H
|
||||
# pragma once
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
|
||||
# define ATTICerr(f, r) ERR_ATTIC_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
|
||||
|
||||
|
||||
/*
|
||||
* ATTIC reason codes.
|
||||
*/
|
||||
# define ATTIC_R_AMBIGUOUS_CONTENT_TYPE 100
|
||||
# define ATTIC_R_BAD_PASSWORD_READ 101
|
||||
# define ATTIC_R_ERROR_VERIFYING_PKCS12_MAC 102
|
||||
# define ATTIC_R_INIT_FAILED 103
|
||||
# define ATTIC_R_PASSPHRASE_CALLBACK_ERROR 104
|
||||
# define ATTIC_R_PATH_MUST_BE_ABSOLUTE 105
|
||||
# define ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 106
|
||||
# define ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED 107
|
||||
# define ATTIC_R_UNSUPPORTED_CONTENT_TYPE 108
|
||||
# define ATTIC_R_UNSUPPORTED_SEARCH_TYPE 109
|
||||
# define ATTIC_R_URI_AUTHORITY_UNSUPPORTED 110
|
||||
|
||||
#endif
|
||||
@@ -1,914 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the OSSLTEST engine. It provides deliberately crippled digest
|
||||
* implementations for test purposes. It is highly insecure and must NOT be
|
||||
* used for any purpose except testing
|
||||
*/
|
||||
|
||||
/* We need to use some engine deprecated APIs */
|
||||
#define OPENSSL_SUPPRESS_DEPRECATED
|
||||
|
||||
/*
|
||||
* SHA low level APIs are deprecated for public use, but still ok for
|
||||
* internal use. Note, that due to symbols not being exported, only the
|
||||
* #defines and type definitions can be accessed, function calls are not
|
||||
* available. The digest lengths, block sizes and sizeof(CTX) are used herein
|
||||
* for several different digests.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "internal/common.h" /* for CHECK_AND_SKIP_CASE_PREFIX */
|
||||
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/modes.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <crypto/evp.h>
|
||||
|
||||
/* clang-format off */
|
||||
#include "e_ossltest_err.c"
|
||||
/* clang-format on */
|
||||
|
||||
/* Engine Id and Name */
|
||||
static const char *engine_ossltest_id = "ossltest";
|
||||
static const char *engine_ossltest_name = "OpenSSL Test engine support";
|
||||
|
||||
|
||||
/* Engine Lifetime functions */
|
||||
static int ossltest_destroy(ENGINE *e);
|
||||
static int ossltest_init(ENGINE *e);
|
||||
static int ossltest_finish(ENGINE *e);
|
||||
void ENGINE_load_ossltest(void);
|
||||
|
||||
|
||||
/* Set up digests */
|
||||
static int ossltest_digests(ENGINE *e, const EVP_MD **digest,
|
||||
const int **nids, int nid);
|
||||
static const RAND_METHOD *ossltest_rand_method(void);
|
||||
|
||||
/* MD5 */
|
||||
static int digest_md5_init(EVP_MD_CTX *ctx);
|
||||
static int digest_md5_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count);
|
||||
static int digest_md5_final(EVP_MD_CTX *ctx, unsigned char *md);
|
||||
|
||||
static EVP_MD *_hidden_md5_md = NULL;
|
||||
static const EVP_MD *digest_md5(void)
|
||||
{
|
||||
if (_hidden_md5_md == NULL) {
|
||||
EVP_MD *md;
|
||||
|
||||
if ((md = EVP_MD_meth_new(NID_md5, NID_md5WithRSAEncryption)) == NULL
|
||||
|| !EVP_MD_meth_set_result_size(md, MD5_DIGEST_LENGTH)
|
||||
|| !EVP_MD_meth_set_input_blocksize(md, MD5_CBLOCK)
|
||||
|| !EVP_MD_meth_set_app_datasize(md,
|
||||
sizeof(EVP_MD *) + sizeof(MD5_CTX))
|
||||
|| !EVP_MD_meth_set_flags(md, 0)
|
||||
|| !EVP_MD_meth_set_init(md, digest_md5_init)
|
||||
|| !EVP_MD_meth_set_update(md, digest_md5_update)
|
||||
|| !EVP_MD_meth_set_final(md, digest_md5_final)) {
|
||||
EVP_MD_meth_free(md);
|
||||
md = NULL;
|
||||
}
|
||||
_hidden_md5_md = md;
|
||||
}
|
||||
return _hidden_md5_md;
|
||||
}
|
||||
|
||||
/* SHA1 */
|
||||
static int digest_sha1_init(EVP_MD_CTX *ctx);
|
||||
static int digest_sha1_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count);
|
||||
static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md);
|
||||
|
||||
static EVP_MD *_hidden_sha1_md = NULL;
|
||||
static const EVP_MD *digest_sha1(void)
|
||||
{
|
||||
if (_hidden_sha1_md == NULL) {
|
||||
EVP_MD *md;
|
||||
|
||||
if ((md = EVP_MD_meth_new(NID_sha1, NID_sha1WithRSAEncryption)) == NULL
|
||||
|| !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
|
||||
|| !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
|
||||
|| !EVP_MD_meth_set_app_datasize(md,
|
||||
sizeof(EVP_MD *) + sizeof(SHA_CTX))
|
||||
|| !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT)
|
||||
|| !EVP_MD_meth_set_init(md, digest_sha1_init)
|
||||
|| !EVP_MD_meth_set_update(md, digest_sha1_update)
|
||||
|| !EVP_MD_meth_set_final(md, digest_sha1_final)) {
|
||||
EVP_MD_meth_free(md);
|
||||
md = NULL;
|
||||
}
|
||||
_hidden_sha1_md = md;
|
||||
}
|
||||
return _hidden_sha1_md;
|
||||
}
|
||||
|
||||
/* SHA256 */
|
||||
static int digest_sha256_init(EVP_MD_CTX *ctx);
|
||||
static int digest_sha256_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count);
|
||||
static int digest_sha256_final(EVP_MD_CTX *ctx, unsigned char *md);
|
||||
|
||||
static EVP_MD *_hidden_sha256_md = NULL;
|
||||
static const EVP_MD *digest_sha256(void)
|
||||
{
|
||||
if (_hidden_sha256_md == NULL) {
|
||||
EVP_MD *md;
|
||||
|
||||
if ((md = EVP_MD_meth_new(NID_sha256, NID_sha256WithRSAEncryption)) == NULL
|
||||
|| !EVP_MD_meth_set_result_size(md, SHA256_DIGEST_LENGTH)
|
||||
|| !EVP_MD_meth_set_input_blocksize(md, SHA256_CBLOCK)
|
||||
|| !EVP_MD_meth_set_app_datasize(md,
|
||||
sizeof(EVP_MD *) + sizeof(SHA256_CTX))
|
||||
|| !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT)
|
||||
|| !EVP_MD_meth_set_init(md, digest_sha256_init)
|
||||
|| !EVP_MD_meth_set_update(md, digest_sha256_update)
|
||||
|| !EVP_MD_meth_set_final(md, digest_sha256_final)) {
|
||||
EVP_MD_meth_free(md);
|
||||
md = NULL;
|
||||
}
|
||||
_hidden_sha256_md = md;
|
||||
}
|
||||
return _hidden_sha256_md;
|
||||
}
|
||||
|
||||
/* SHA384/SHA512 */
|
||||
static int digest_sha384_init(EVP_MD_CTX *ctx);
|
||||
static int digest_sha384_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count);
|
||||
static int digest_sha384_final(EVP_MD_CTX *ctx, unsigned char *md);
|
||||
|
||||
static int digest_sha512_init(EVP_MD_CTX *ctx);
|
||||
static int digest_sha512_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count);
|
||||
static int digest_sha512_final(EVP_MD_CTX *ctx, unsigned char *md);
|
||||
|
||||
static EVP_MD *_hidden_sha384_md = NULL;
|
||||
static const EVP_MD *digest_sha384(void)
|
||||
{
|
||||
if (_hidden_sha384_md == NULL) {
|
||||
EVP_MD *md;
|
||||
|
||||
if ((md = EVP_MD_meth_new(NID_sha384, NID_sha384WithRSAEncryption)) == NULL
|
||||
|| !EVP_MD_meth_set_result_size(md, SHA384_DIGEST_LENGTH)
|
||||
|| !EVP_MD_meth_set_input_blocksize(md, SHA512_CBLOCK)
|
||||
|| !EVP_MD_meth_set_app_datasize(md,
|
||||
sizeof(EVP_MD *) + sizeof(SHA512_CTX))
|
||||
|| !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT)
|
||||
|| !EVP_MD_meth_set_init(md, digest_sha384_init)
|
||||
|| !EVP_MD_meth_set_update(md, digest_sha384_update)
|
||||
|| !EVP_MD_meth_set_final(md, digest_sha384_final)) {
|
||||
EVP_MD_meth_free(md);
|
||||
md = NULL;
|
||||
}
|
||||
_hidden_sha384_md = md;
|
||||
}
|
||||
return _hidden_sha384_md;
|
||||
}
|
||||
static EVP_MD *_hidden_sha512_md = NULL;
|
||||
static const EVP_MD *digest_sha512(void)
|
||||
{
|
||||
if (_hidden_sha512_md == NULL) {
|
||||
EVP_MD *md;
|
||||
|
||||
if ((md = EVP_MD_meth_new(NID_sha512, NID_sha512WithRSAEncryption)) == NULL
|
||||
|| !EVP_MD_meth_set_result_size(md, SHA512_DIGEST_LENGTH)
|
||||
|| !EVP_MD_meth_set_input_blocksize(md, SHA512_CBLOCK)
|
||||
|| !EVP_MD_meth_set_app_datasize(md,
|
||||
sizeof(EVP_MD *) + sizeof(SHA512_CTX))
|
||||
|| !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT)
|
||||
|| !EVP_MD_meth_set_init(md, digest_sha512_init)
|
||||
|| !EVP_MD_meth_set_update(md, digest_sha512_update)
|
||||
|| !EVP_MD_meth_set_final(md, digest_sha512_final)) {
|
||||
EVP_MD_meth_free(md);
|
||||
md = NULL;
|
||||
}
|
||||
_hidden_sha512_md = md;
|
||||
}
|
||||
return _hidden_sha512_md;
|
||||
}
|
||||
static void destroy_digests(void)
|
||||
{
|
||||
EVP_MD_meth_free(_hidden_md5_md);
|
||||
_hidden_md5_md = NULL;
|
||||
EVP_MD_meth_free(_hidden_sha1_md);
|
||||
_hidden_sha1_md = NULL;
|
||||
EVP_MD_meth_free(_hidden_sha256_md);
|
||||
_hidden_sha256_md = NULL;
|
||||
EVP_MD_meth_free(_hidden_sha384_md);
|
||||
_hidden_sha384_md = NULL;
|
||||
EVP_MD_meth_free(_hidden_sha512_md);
|
||||
_hidden_sha512_md = NULL;
|
||||
}
|
||||
static int ossltest_digest_nids(const int **nids)
|
||||
{
|
||||
static int digest_nids[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
static int pos = 0;
|
||||
static int init = 0;
|
||||
|
||||
if (!init) {
|
||||
const EVP_MD *md;
|
||||
if ((md = digest_md5()) != NULL)
|
||||
digest_nids[pos++] = EVP_MD_get_type(md);
|
||||
if ((md = digest_sha1()) != NULL)
|
||||
digest_nids[pos++] = EVP_MD_get_type(md);
|
||||
if ((md = digest_sha256()) != NULL)
|
||||
digest_nids[pos++] = EVP_MD_get_type(md);
|
||||
if ((md = digest_sha384()) != NULL)
|
||||
digest_nids[pos++] = EVP_MD_get_type(md);
|
||||
if ((md = digest_sha512()) != NULL)
|
||||
digest_nids[pos++] = EVP_MD_get_type(md);
|
||||
digest_nids[pos] = 0;
|
||||
init = 1;
|
||||
}
|
||||
*nids = digest_nids;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* Setup ciphers */
|
||||
static int ossltest_ciphers(ENGINE *, const EVP_CIPHER **,
|
||||
const int **, int);
|
||||
|
||||
static int ossltest_cipher_nids[] = {
|
||||
NID_aes_128_cbc, NID_aes_128_gcm,
|
||||
NID_aes_128_cbc_hmac_sha1, 0
|
||||
};
|
||||
|
||||
/* AES128 */
|
||||
|
||||
static int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv, int enc);
|
||||
static int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl);
|
||||
static int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv, int enc);
|
||||
static int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl);
|
||||
static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
|
||||
void *ptr);
|
||||
static int ossltest_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int enc);
|
||||
static int ossltest_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx,
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
size_t inl);
|
||||
static int ossltest_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
|
||||
int arg, void *ptr);
|
||||
|
||||
typedef struct {
|
||||
size_t payload_length; /* AAD length in decrypt case */
|
||||
unsigned int tls_ver;
|
||||
} EVP_AES_HMAC_SHA1;
|
||||
|
||||
static EVP_CIPHER *_hidden_aes_128_cbc = NULL;
|
||||
static const EVP_CIPHER *ossltest_aes_128_cbc(void)
|
||||
{
|
||||
if (_hidden_aes_128_cbc == NULL
|
||||
&& ((_hidden_aes_128_cbc = EVP_CIPHER_meth_new(NID_aes_128_cbc,
|
||||
16 /* block size */,
|
||||
16 /* key len */)) == NULL
|
||||
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc,16)
|
||||
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc,
|
||||
EVP_CIPH_FLAG_DEFAULT_ASN1
|
||||
| EVP_CIPH_CBC_MODE)
|
||||
|| !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc,
|
||||
ossltest_aes128_init_key)
|
||||
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc,
|
||||
ossltest_aes128_cbc_cipher)
|
||||
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc,
|
||||
EVP_CIPHER_impl_ctx_size(EVP_aes_128_cbc())))) {
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_cbc);
|
||||
_hidden_aes_128_cbc = NULL;
|
||||
}
|
||||
return _hidden_aes_128_cbc;
|
||||
}
|
||||
|
||||
static EVP_CIPHER *_hidden_aes_128_gcm = NULL;
|
||||
|
||||
#define AES_GCM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
|
||||
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
|
||||
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
|
||||
| EVP_CIPH_CUSTOM_COPY |EVP_CIPH_FLAG_AEAD_CIPHER \
|
||||
| EVP_CIPH_GCM_MODE)
|
||||
|
||||
static const EVP_CIPHER *ossltest_aes_128_gcm(void)
|
||||
{
|
||||
if (_hidden_aes_128_gcm == NULL
|
||||
&& ((_hidden_aes_128_gcm = EVP_CIPHER_meth_new(NID_aes_128_gcm,
|
||||
1 /* block size */,
|
||||
16 /* key len */)) == NULL
|
||||
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_gcm,12)
|
||||
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_128_gcm, AES_GCM_FLAGS)
|
||||
|| !EVP_CIPHER_meth_set_init(_hidden_aes_128_gcm,
|
||||
ossltest_aes128_gcm_init_key)
|
||||
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_gcm,
|
||||
ossltest_aes128_gcm_cipher)
|
||||
|| !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_gcm,
|
||||
ossltest_aes128_gcm_ctrl)
|
||||
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_gcm,
|
||||
EVP_CIPHER_impl_ctx_size(EVP_aes_128_gcm())))) {
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_gcm);
|
||||
_hidden_aes_128_gcm = NULL;
|
||||
}
|
||||
return _hidden_aes_128_gcm;
|
||||
}
|
||||
|
||||
static EVP_CIPHER *_hidden_aes_128_cbc_hmac_sha1 = NULL;
|
||||
|
||||
static const EVP_CIPHER *ossltest_aes_128_cbc_hmac_sha1(void)
|
||||
{
|
||||
if (_hidden_aes_128_cbc_hmac_sha1 == NULL
|
||||
&& ((_hidden_aes_128_cbc_hmac_sha1
|
||||
= EVP_CIPHER_meth_new(NID_aes_128_cbc_hmac_sha1,
|
||||
16 /* block size */,
|
||||
16 /* key len */)) == NULL
|
||||
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc_hmac_sha1,16)
|
||||
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc_hmac_sha1,
|
||||
EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
|
||||
EVP_CIPH_FLAG_AEAD_CIPHER)
|
||||
|| !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc_hmac_sha1,
|
||||
ossltest_aes128_cbc_hmac_sha1_init_key)
|
||||
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc_hmac_sha1,
|
||||
ossltest_aes128_cbc_hmac_sha1_cipher)
|
||||
|| !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc_hmac_sha1,
|
||||
ossltest_aes128_cbc_hmac_sha1_ctrl)
|
||||
|| !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_128_cbc_hmac_sha1,
|
||||
EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv)
|
||||
|| !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_128_cbc_hmac_sha1,
|
||||
EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv)
|
||||
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc_hmac_sha1,
|
||||
sizeof(EVP_AES_HMAC_SHA1)))) {
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1);
|
||||
_hidden_aes_128_cbc_hmac_sha1 = NULL;
|
||||
}
|
||||
return _hidden_aes_128_cbc_hmac_sha1;
|
||||
}
|
||||
|
||||
static void destroy_ciphers(void)
|
||||
{
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_cbc);
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_gcm);
|
||||
EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1);
|
||||
_hidden_aes_128_cbc = NULL;
|
||||
_hidden_aes_128_gcm = NULL;
|
||||
_hidden_aes_128_cbc_hmac_sha1 = NULL;
|
||||
}
|
||||
|
||||
/* Key loading */
|
||||
static EVP_PKEY *load_key(ENGINE *eng, const char *key_id, int pub,
|
||||
UI_METHOD *ui_method, void *ui_data)
|
||||
{
|
||||
BIO *in;
|
||||
EVP_PKEY *key;
|
||||
|
||||
if (!CHECK_AND_SKIP_CASE_PREFIX(key_id, "ot:"))
|
||||
return NULL;
|
||||
|
||||
fprintf(stderr, "[ossltest]Loading %s key %s\n",
|
||||
pub ? "Public" : "Private", key_id);
|
||||
in = BIO_new_file(key_id, "r");
|
||||
if (!in)
|
||||
return NULL;
|
||||
if (pub)
|
||||
key = PEM_read_bio_PUBKEY(in, NULL, 0, NULL);
|
||||
else
|
||||
key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL);
|
||||
BIO_free(in);
|
||||
return key;
|
||||
}
|
||||
|
||||
static EVP_PKEY *ossltest_load_privkey(ENGINE *eng, const char *key_id,
|
||||
UI_METHOD *ui_method, void *ui_data)
|
||||
{
|
||||
return load_key(eng, key_id, 0, ui_method, ui_data);
|
||||
}
|
||||
|
||||
static EVP_PKEY *ossltest_load_pubkey(ENGINE *eng, const char *key_id,
|
||||
UI_METHOD *ui_method, void *ui_data)
|
||||
{
|
||||
return load_key(eng, key_id, 1, ui_method, ui_data);
|
||||
}
|
||||
|
||||
|
||||
static int bind_ossltest(ENGINE *e)
|
||||
{
|
||||
/* Ensure the ossltest error handling is set up */
|
||||
ERR_load_OSSLTEST_strings();
|
||||
|
||||
if (!ENGINE_set_id(e, engine_ossltest_id)
|
||||
|| !ENGINE_set_name(e, engine_ossltest_name)
|
||||
|| !ENGINE_set_digests(e, ossltest_digests)
|
||||
|| !ENGINE_set_ciphers(e, ossltest_ciphers)
|
||||
|| !ENGINE_set_RAND(e, ossltest_rand_method())
|
||||
|| !ENGINE_set_destroy_function(e, ossltest_destroy)
|
||||
|| !ENGINE_set_load_privkey_function(e, ossltest_load_privkey)
|
||||
|| !ENGINE_set_load_pubkey_function(e, ossltest_load_pubkey)
|
||||
|| !ENGINE_set_init_function(e, ossltest_init)
|
||||
|| !ENGINE_set_finish_function(e, ossltest_finish)) {
|
||||
OSSLTESTerr(OSSLTEST_F_BIND_OSSLTEST, OSSLTEST_R_INIT_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ENGINE *engine_ossltest(void)
|
||||
{
|
||||
ENGINE *ret = ENGINE_new();
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
if (!bind_ossltest(ret)) {
|
||||
ENGINE_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ENGINE_load_ossltest(void)
|
||||
{
|
||||
/* Copied from eng_[openssl|dyn].c */
|
||||
ENGINE *toadd = engine_ossltest();
|
||||
if (!toadd)
|
||||
return;
|
||||
ENGINE_add(toadd);
|
||||
ENGINE_free(toadd);
|
||||
ERR_clear_error();
|
||||
}
|
||||
|
||||
|
||||
static int ossltest_init(ENGINE *e)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int ossltest_finish(ENGINE *e)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int ossltest_destroy(ENGINE *e)
|
||||
{
|
||||
destroy_digests();
|
||||
destroy_ciphers();
|
||||
ERR_unload_OSSLTEST_strings();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ossltest_digests(ENGINE *e, const EVP_MD **digest,
|
||||
const int **nids, int nid)
|
||||
{
|
||||
int ok = 1;
|
||||
if (!digest) {
|
||||
/* We are returning a list of supported nids */
|
||||
return ossltest_digest_nids(nids);
|
||||
}
|
||||
/* We are being asked for a specific digest */
|
||||
switch (nid) {
|
||||
case NID_md5:
|
||||
*digest = digest_md5();
|
||||
break;
|
||||
case NID_sha1:
|
||||
*digest = digest_sha1();
|
||||
break;
|
||||
case NID_sha256:
|
||||
*digest = digest_sha256();
|
||||
break;
|
||||
case NID_sha384:
|
||||
*digest = digest_sha384();
|
||||
break;
|
||||
case NID_sha512:
|
||||
*digest = digest_sha512();
|
||||
break;
|
||||
default:
|
||||
ok = 0;
|
||||
*digest = NULL;
|
||||
break;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ossltest_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
|
||||
const int **nids, int nid)
|
||||
{
|
||||
int ok = 1;
|
||||
if (!cipher) {
|
||||
/* We are returning a list of supported nids */
|
||||
*nids = ossltest_cipher_nids;
|
||||
return (sizeof(ossltest_cipher_nids) - 1)
|
||||
/ sizeof(ossltest_cipher_nids[0]);
|
||||
}
|
||||
/* We are being asked for a specific cipher */
|
||||
switch (nid) {
|
||||
case NID_aes_128_cbc:
|
||||
*cipher = ossltest_aes_128_cbc();
|
||||
break;
|
||||
case NID_aes_128_gcm:
|
||||
*cipher = ossltest_aes_128_gcm();
|
||||
break;
|
||||
case NID_aes_128_cbc_hmac_sha1:
|
||||
*cipher = ossltest_aes_128_cbc_hmac_sha1();
|
||||
break;
|
||||
default:
|
||||
ok = 0;
|
||||
*cipher = NULL;
|
||||
break;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void fill_known_data(unsigned char *md, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
md[i] = (unsigned char)(i & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 implementation. We go through the motions of doing MD5 by deferring to
|
||||
* the standard implementation. Then we overwrite the result with a will defined
|
||||
* value, so that all "MD5" digests using the test engine always end up with
|
||||
* the same value.
|
||||
*/
|
||||
static int digest_md5_init(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return EVP_MD_meth_get_init(EVP_md5())(ctx);
|
||||
}
|
||||
|
||||
static int digest_md5_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count)
|
||||
{
|
||||
return EVP_MD_meth_get_update(EVP_md5())(ctx, data, count);
|
||||
}
|
||||
|
||||
static int digest_md5_final(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
int ret = EVP_MD_meth_get_final(EVP_md5())(ctx, md);
|
||||
|
||||
if (ret > 0) {
|
||||
fill_known_data(md, MD5_DIGEST_LENGTH);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA1 implementation.
|
||||
*/
|
||||
static int digest_sha1_init(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return EVP_MD_meth_get_init(EVP_sha1())(ctx);
|
||||
}
|
||||
|
||||
static int digest_sha1_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count)
|
||||
{
|
||||
return EVP_MD_meth_get_update(EVP_sha1())(ctx, data, count);
|
||||
}
|
||||
|
||||
static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
int ret = EVP_MD_meth_get_final(EVP_sha1())(ctx, md);
|
||||
|
||||
if (ret > 0) {
|
||||
fill_known_data(md, SHA_DIGEST_LENGTH);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA256 implementation.
|
||||
*/
|
||||
static int digest_sha256_init(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return EVP_MD_meth_get_init(EVP_sha256())(ctx);
|
||||
}
|
||||
|
||||
static int digest_sha256_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count)
|
||||
{
|
||||
return EVP_MD_meth_get_update(EVP_sha256())(ctx, data, count);
|
||||
}
|
||||
|
||||
static int digest_sha256_final(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
int ret = EVP_MD_meth_get_final(EVP_sha256())(ctx, md);
|
||||
|
||||
if (ret > 0) {
|
||||
fill_known_data(md, SHA256_DIGEST_LENGTH);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA384 implementation.
|
||||
*/
|
||||
static int digest_sha384_init(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return EVP_MD_meth_get_init(EVP_sha384())(ctx);
|
||||
}
|
||||
|
||||
static int digest_sha384_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count)
|
||||
{
|
||||
return EVP_MD_meth_get_update(EVP_sha384())(ctx, data, count);
|
||||
}
|
||||
|
||||
static int digest_sha384_final(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
int ret = EVP_MD_meth_get_final(EVP_sha384())(ctx, md);
|
||||
|
||||
if (ret > 0) {
|
||||
fill_known_data(md, SHA384_DIGEST_LENGTH);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA512 implementation.
|
||||
*/
|
||||
static int digest_sha512_init(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return EVP_MD_meth_get_init(EVP_sha512())(ctx);
|
||||
}
|
||||
|
||||
static int digest_sha512_update(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t count)
|
||||
{
|
||||
return EVP_MD_meth_get_update(EVP_sha512())(ctx, data, count);
|
||||
}
|
||||
|
||||
static int digest_sha512_final(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
int ret = EVP_MD_meth_get_final(EVP_sha512())(ctx, md);
|
||||
|
||||
if (ret > 0) {
|
||||
fill_known_data(md, SHA512_DIGEST_LENGTH);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES128 Implementation
|
||||
*/
|
||||
|
||||
static int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
return EVP_CIPHER_meth_get_init(EVP_aes_128_cbc()) (ctx, key, iv, enc);
|
||||
}
|
||||
|
||||
static int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
unsigned char *tmpbuf;
|
||||
int ret;
|
||||
|
||||
tmpbuf = OPENSSL_malloc(inl);
|
||||
|
||||
/* OPENSSL_malloc will return NULL if inl == 0 */
|
||||
if (tmpbuf == NULL && inl > 0)
|
||||
return -1;
|
||||
|
||||
/* Remember what we were asked to encrypt */
|
||||
if (tmpbuf != NULL)
|
||||
memcpy(tmpbuf, in, inl);
|
||||
|
||||
/* Go through the motions of encrypting it */
|
||||
ret = EVP_CIPHER_meth_get_do_cipher(EVP_aes_128_cbc())(ctx, out, in, inl);
|
||||
|
||||
/* Throw it all away and just use the plaintext as the output */
|
||||
if (tmpbuf != NULL)
|
||||
memcpy(out, tmpbuf, inl);
|
||||
OPENSSL_free(tmpbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
return EVP_CIPHER_meth_get_init(EVP_aes_128_gcm()) (ctx, key, iv, enc);
|
||||
}
|
||||
|
||||
static int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
unsigned char *tmpbuf = OPENSSL_malloc(inl);
|
||||
|
||||
/* OPENSSL_malloc will return NULL if inl == 0 */
|
||||
if (tmpbuf == NULL && inl > 0)
|
||||
return -1;
|
||||
|
||||
/* Remember what we were asked to encrypt */
|
||||
if (tmpbuf != NULL)
|
||||
memcpy(tmpbuf, in, inl);
|
||||
|
||||
/* Go through the motions of encrypting it */
|
||||
EVP_CIPHER_meth_get_do_cipher(EVP_aes_128_gcm())(ctx, out, in, inl);
|
||||
|
||||
/* Throw it all away and just use the plaintext as the output */
|
||||
if (tmpbuf != NULL && out != NULL)
|
||||
memcpy(out, tmpbuf, inl);
|
||||
OPENSSL_free(tmpbuf);
|
||||
|
||||
return (int)inl;
|
||||
}
|
||||
|
||||
static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
|
||||
void *ptr)
|
||||
{
|
||||
/* Pass the ctrl down */
|
||||
int ret = EVP_CIPHER_meth_get_ctrl(EVP_aes_128_gcm())(ctx, type, arg, ptr);
|
||||
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
switch (type) {
|
||||
case EVP_CTRL_AEAD_GET_TAG:
|
||||
/* Always give the same tag */
|
||||
memset(ptr, 0, EVP_GCM_TLS_TAG_LEN);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define NO_PAYLOAD_LENGTH ((size_t)-1)
|
||||
# define data(ctx) ((EVP_AES_HMAC_SHA1 *)EVP_CIPHER_CTX_get_cipher_data(ctx))
|
||||
|
||||
static int ossltest_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *inkey,
|
||||
const unsigned char *iv,
|
||||
int enc)
|
||||
{
|
||||
EVP_AES_HMAC_SHA1 *key = data(ctx);
|
||||
key->payload_length = NO_PAYLOAD_LENGTH;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ossltest_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx,
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
size_t len)
|
||||
{
|
||||
EVP_AES_HMAC_SHA1 *key = data(ctx);
|
||||
unsigned int l;
|
||||
size_t plen = key->payload_length;
|
||||
|
||||
key->payload_length = NO_PAYLOAD_LENGTH;
|
||||
|
||||
if (len % AES_BLOCK_SIZE)
|
||||
return 0;
|
||||
|
||||
if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
|
||||
if (plen == NO_PAYLOAD_LENGTH)
|
||||
plen = len;
|
||||
else if (len !=
|
||||
((plen + SHA_DIGEST_LENGTH +
|
||||
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
|
||||
return 0;
|
||||
|
||||
memmove(out, in, plen);
|
||||
|
||||
if (plen != len) { /* "TLS" mode of operation */
|
||||
/* calculate HMAC and append it to payload */
|
||||
fill_known_data(out + plen, SHA_DIGEST_LENGTH);
|
||||
|
||||
/* pad the payload|hmac */
|
||||
plen += SHA_DIGEST_LENGTH;
|
||||
for (l = (unsigned int)(len - plen - 1); plen < len; plen++)
|
||||
out[plen] = l;
|
||||
}
|
||||
} else {
|
||||
/* decrypt HMAC|padding at once */
|
||||
memmove(out, in, len);
|
||||
|
||||
if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
|
||||
unsigned int maxpad, pad;
|
||||
|
||||
if (key->tls_ver >= TLS1_1_VERSION) {
|
||||
if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1))
|
||||
return 0;
|
||||
|
||||
/* omit explicit iv */
|
||||
in += AES_BLOCK_SIZE;
|
||||
out += AES_BLOCK_SIZE;
|
||||
len -= AES_BLOCK_SIZE;
|
||||
} else if (len < (SHA_DIGEST_LENGTH + 1))
|
||||
return 0;
|
||||
|
||||
/* figure out payload length */
|
||||
pad = out[len - 1];
|
||||
maxpad = (unsigned int)(len - (SHA_DIGEST_LENGTH + 1));
|
||||
if (pad > maxpad)
|
||||
return 0;
|
||||
for (plen = len - pad - 1; plen < len; plen++)
|
||||
if (out[plen] != pad)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ossltest_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
|
||||
int arg, void *ptr)
|
||||
{
|
||||
EVP_AES_HMAC_SHA1 *key = data(ctx);
|
||||
|
||||
switch (type) {
|
||||
case EVP_CTRL_AEAD_SET_MAC_KEY:
|
||||
return 1;
|
||||
|
||||
case EVP_CTRL_AEAD_TLS1_AAD:
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
unsigned int len;
|
||||
|
||||
if (arg != EVP_AEAD_TLS1_AAD_LEN)
|
||||
return -1;
|
||||
|
||||
len = p[arg - 2] << 8 | p[arg - 1];
|
||||
key->tls_ver = p[arg - 4] << 8 | p[arg - 3];
|
||||
|
||||
if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
|
||||
key->payload_length = len;
|
||||
if (key->tls_ver >= TLS1_1_VERSION) {
|
||||
if (len < AES_BLOCK_SIZE)
|
||||
return 0;
|
||||
len -= AES_BLOCK_SIZE;
|
||||
p[arg - 2] = len >> 8;
|
||||
p[arg - 1] = len;
|
||||
}
|
||||
|
||||
return (int)(((len + SHA_DIGEST_LENGTH +
|
||||
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
|
||||
- len);
|
||||
} else {
|
||||
key->payload_length = arg;
|
||||
|
||||
return SHA_DIGEST_LENGTH;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int ossltest_rand_bytes(unsigned char *buf, int num)
|
||||
{
|
||||
unsigned char val = 1;
|
||||
|
||||
while (--num >= 0)
|
||||
*buf++ = val++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ossltest_rand_status(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const RAND_METHOD *ossltest_rand_method(void)
|
||||
{
|
||||
|
||||
static RAND_METHOD osslt_rand_meth = {
|
||||
NULL,
|
||||
ossltest_rand_bytes,
|
||||
NULL,
|
||||
NULL,
|
||||
ossltest_rand_bytes,
|
||||
ossltest_rand_status
|
||||
};
|
||||
|
||||
return &osslt_rand_meth;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
# The INPUT HEADER is scanned for declarations
|
||||
# LIBNAME INPUT HEADER ERROR-TABLE FILE
|
||||
L OSSLTEST e_ossltest_err.h e_ossltest_err.c
|
||||
@@ -1,9 +0,0 @@
|
||||
# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
#Reason codes
|
||||
OSSLTEST_R_INIT_FAILED:100:init failed
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include "e_ossltest_err.h"
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static ERR_STRING_DATA OSSLTEST_str_reasons[] = {
|
||||
{ERR_PACK(0, 0, OSSLTEST_R_INIT_FAILED), "init failed"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int lib_code = 0;
|
||||
static int error_loaded = 0;
|
||||
|
||||
static int ERR_load_OSSLTEST_strings(void)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
|
||||
if (!error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_load_strings(lib_code, OSSLTEST_str_reasons);
|
||||
#endif
|
||||
error_loaded = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ERR_unload_OSSLTEST_strings(void)
|
||||
{
|
||||
if (error_loaded) {
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
ERR_unload_strings(lib_code, OSSLTEST_str_reasons);
|
||||
#endif
|
||||
error_loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ERR_OSSLTEST_error(int function, int reason, const char *file, int line)
|
||||
{
|
||||
if (lib_code == 0)
|
||||
lib_code = ERR_get_next_error_library();
|
||||
ERR_raise(lib_code, reason);
|
||||
ERR_set_debug(file, line, NULL);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OSSL_E_OSSLTEST_ERR_H
|
||||
# define OSSL_E_OSSLTEST_ERR_H
|
||||
# pragma once
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
|
||||
# define OSSLTESTerr(f, r) ERR_OSSLTEST_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
|
||||
|
||||
|
||||
/*
|
||||
* OSSLTEST reason codes.
|
||||
*/
|
||||
# define OSSLTEST_R_INIT_FAILED 100
|
||||
|
||||
#endif
|
||||
@@ -1,727 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file uses the low level AES and engine functions (which are deprecated
|
||||
* for non-internal use) in order to implement the padlock engine AES ciphers.
|
||||
*/
|
||||
#define OPENSSL_SUPPRESS_DEPRECATED
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/modes.h>
|
||||
|
||||
#ifndef OPENSSL_NO_PADLOCKENG
|
||||
|
||||
/*
|
||||
* VIA PadLock AES is available *ONLY* on some x86 CPUs. Not only that it
|
||||
* doesn't exist elsewhere, but it even can't be compiled on other platforms!
|
||||
*/
|
||||
|
||||
# undef COMPILE_PADLOCKENG
|
||||
# if defined(PADLOCK_ASM)
|
||||
# define COMPILE_PADLOCKENG
|
||||
static ENGINE *ENGINE_padlock(void);
|
||||
# endif
|
||||
|
||||
void engine_load_padlock_int(void);
|
||||
void engine_load_padlock_int(void)
|
||||
{
|
||||
/* On non-x86 CPUs it just returns. */
|
||||
# ifdef COMPILE_PADLOCKENG
|
||||
ENGINE *toadd = ENGINE_padlock();
|
||||
if (!toadd)
|
||||
return;
|
||||
ERR_set_mark();
|
||||
ENGINE_add(toadd);
|
||||
/*
|
||||
* If the "add" worked, it gets a structural reference. So either way, we
|
||||
* release our just-created reference.
|
||||
*/
|
||||
ENGINE_free(toadd);
|
||||
/*
|
||||
* If the "add" didn't work, it was probably a conflict because it was
|
||||
* already added (eg. someone calling ENGINE_load_blah then calling
|
||||
* ENGINE_load_builtin_engines() perhaps).
|
||||
*/
|
||||
ERR_pop_to_mark();
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef COMPILE_PADLOCKENG
|
||||
|
||||
/* Function for ENGINE detection and control */
|
||||
static int padlock_available(void);
|
||||
static int padlock_init(ENGINE *e);
|
||||
|
||||
/* RNG Stuff */
|
||||
static RAND_METHOD padlock_rand;
|
||||
|
||||
/* Cipher Stuff */
|
||||
static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
|
||||
const int **nids, int nid);
|
||||
|
||||
/* Engine names */
|
||||
static const char *padlock_id = "padlock";
|
||||
static char padlock_name[100];
|
||||
|
||||
/* Available features */
|
||||
static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
|
||||
static int padlock_use_rng = 0; /* Random Number Generator */
|
||||
|
||||
/* ===== Engine "management" functions ===== */
|
||||
|
||||
/* Prepare the ENGINE structure for registration */
|
||||
static int padlock_bind_helper(ENGINE *e)
|
||||
{
|
||||
/* Check available features */
|
||||
padlock_available();
|
||||
|
||||
/*
|
||||
* RNG is currently disabled for reasons discussed in commentary just
|
||||
* before padlock_rand_bytes function.
|
||||
*/
|
||||
padlock_use_rng = 0;
|
||||
|
||||
/* Generate a nice engine name with available features */
|
||||
BIO_snprintf(padlock_name, sizeof(padlock_name),
|
||||
"VIA PadLock (%s, %s)",
|
||||
padlock_use_rng ? "RNG" : "no-RNG",
|
||||
padlock_use_ace ? "ACE" : "no-ACE");
|
||||
|
||||
/* Register everything or return with an error */
|
||||
if (!ENGINE_set_id(e, padlock_id) ||
|
||||
!ENGINE_set_name(e, padlock_name) ||
|
||||
!ENGINE_set_init_function(e, padlock_init) ||
|
||||
(padlock_use_ace && !ENGINE_set_ciphers(e, padlock_ciphers)) ||
|
||||
(padlock_use_rng && !ENGINE_set_RAND(e, &padlock_rand))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Everything looks good */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Constructor */
|
||||
static ENGINE *ENGINE_padlock(void)
|
||||
{
|
||||
ENGINE *eng = ENGINE_new();
|
||||
|
||||
if (eng == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!padlock_bind_helper(eng)) {
|
||||
ENGINE_free(eng);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return eng;
|
||||
}
|
||||
|
||||
/* Check availability of the engine */
|
||||
static int padlock_init(ENGINE *e)
|
||||
{
|
||||
return (padlock_use_rng || padlock_use_ace);
|
||||
}
|
||||
|
||||
# ifndef AES_ASM
|
||||
static int padlock_aes_set_encrypt_key(const unsigned char *userKey,
|
||||
const int bits,
|
||||
AES_KEY *key);
|
||||
static int padlock_aes_set_decrypt_key(const unsigned char *userKey,
|
||||
const int bits,
|
||||
AES_KEY *key);
|
||||
# define AES_ASM
|
||||
# define AES_set_encrypt_key padlock_aes_set_encrypt_key
|
||||
# define AES_set_decrypt_key padlock_aes_set_decrypt_key
|
||||
/* clang-format off */
|
||||
# include "../crypto/aes/aes_core.c"
|
||||
/* clang-format on */
|
||||
# endif
|
||||
|
||||
/*
|
||||
* This stuff is needed if this ENGINE is being compiled into a
|
||||
* self-contained shared-library.
|
||||
*/
|
||||
/* ===== Here comes the "real" engine ===== */
|
||||
|
||||
/* Some AES-related constants */
|
||||
# define AES_BLOCK_SIZE 16
|
||||
# define AES_KEY_SIZE_128 16
|
||||
# define AES_KEY_SIZE_192 24
|
||||
# define AES_KEY_SIZE_256 32
|
||||
/*
|
||||
* Here we store the status information relevant to the current context.
|
||||
*/
|
||||
/*
|
||||
* BIG FAT WARNING: Inline assembler in PADLOCK_XCRYPT_ASM() depends on
|
||||
* the order of items in this structure. Don't blindly modify, reorder,
|
||||
* etc!
|
||||
*/
|
||||
struct padlock_cipher_data {
|
||||
unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */
|
||||
union {
|
||||
unsigned int pad[4];
|
||||
struct {
|
||||
int rounds:4;
|
||||
int dgst:1; /* n/a in C3 */
|
||||
int align:1; /* n/a in C3 */
|
||||
int cipher:1; /* n/a in C3 */
|
||||
unsigned int keygen:1;
|
||||
int intern:1;
|
||||
unsigned int encdec:1;
|
||||
int ksize:2;
|
||||
} b;
|
||||
} cword; /* Control word */
|
||||
AES_KEY ks; /* Encryption key */
|
||||
};
|
||||
|
||||
/* Interface to assembler module */
|
||||
unsigned int padlock_capability(void);
|
||||
void padlock_key_bswap(AES_KEY *key);
|
||||
void padlock_verify_context(struct padlock_cipher_data *ctx);
|
||||
void padlock_reload_key(void);
|
||||
void padlock_aes_block(void *out, const void *inp,
|
||||
struct padlock_cipher_data *ctx);
|
||||
int padlock_ecb_encrypt(void *out, const void *inp,
|
||||
struct padlock_cipher_data *ctx, size_t len);
|
||||
int padlock_cbc_encrypt(void *out, const void *inp,
|
||||
struct padlock_cipher_data *ctx, size_t len);
|
||||
int padlock_cfb_encrypt(void *out, const void *inp,
|
||||
struct padlock_cipher_data *ctx, size_t len);
|
||||
int padlock_ofb_encrypt(void *out, const void *inp,
|
||||
struct padlock_cipher_data *ctx, size_t len);
|
||||
int padlock_ctr32_encrypt(void *out, const void *inp,
|
||||
struct padlock_cipher_data *ctx, size_t len);
|
||||
int padlock_xstore(void *out, int edx);
|
||||
void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len);
|
||||
void padlock_sha1(void *ctx, const void *inp, size_t len);
|
||||
void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len);
|
||||
void padlock_sha256(void *ctx, const void *inp, size_t len);
|
||||
|
||||
/*
|
||||
* Load supported features of the CPU to see if the PadLock is available.
|
||||
*/
|
||||
static int padlock_available(void)
|
||||
{
|
||||
unsigned int edx = padlock_capability();
|
||||
|
||||
/* Fill up some flags */
|
||||
padlock_use_ace = ((edx & (0x3 << 6)) == (0x3 << 6));
|
||||
padlock_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2));
|
||||
|
||||
return padlock_use_ace + padlock_use_rng;
|
||||
}
|
||||
|
||||
/* ===== AES encryption/decryption ===== */
|
||||
|
||||
# if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
|
||||
# define NID_aes_128_cfb NID_aes_128_cfb128
|
||||
# endif
|
||||
|
||||
# if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
|
||||
# define NID_aes_128_ofb NID_aes_128_ofb128
|
||||
# endif
|
||||
|
||||
# if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
|
||||
# define NID_aes_192_cfb NID_aes_192_cfb128
|
||||
# endif
|
||||
|
||||
# if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
|
||||
# define NID_aes_192_ofb NID_aes_192_ofb128
|
||||
# endif
|
||||
|
||||
# if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
|
||||
# define NID_aes_256_cfb NID_aes_256_cfb128
|
||||
# endif
|
||||
|
||||
# if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
|
||||
# define NID_aes_256_ofb NID_aes_256_ofb128
|
||||
# endif
|
||||
|
||||
/* List of supported ciphers. */
|
||||
static const int padlock_cipher_nids[] = {
|
||||
NID_aes_128_ecb,
|
||||
NID_aes_128_cbc,
|
||||
NID_aes_128_cfb,
|
||||
NID_aes_128_ofb,
|
||||
NID_aes_128_ctr,
|
||||
|
||||
NID_aes_192_ecb,
|
||||
NID_aes_192_cbc,
|
||||
NID_aes_192_cfb,
|
||||
NID_aes_192_ofb,
|
||||
NID_aes_192_ctr,
|
||||
|
||||
NID_aes_256_ecb,
|
||||
NID_aes_256_cbc,
|
||||
NID_aes_256_cfb,
|
||||
NID_aes_256_ofb,
|
||||
NID_aes_256_ctr
|
||||
};
|
||||
|
||||
static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) /
|
||||
sizeof(padlock_cipher_nids[0]));
|
||||
|
||||
/* Function prototypes ... */
|
||||
static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc);
|
||||
|
||||
# define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \
|
||||
( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) )
|
||||
# define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
|
||||
NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx)))
|
||||
|
||||
static int
|
||||
padlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
|
||||
const unsigned char *in_arg, size_t nbytes)
|
||||
{
|
||||
return padlock_ecb_encrypt(out_arg, in_arg,
|
||||
ALIGNED_CIPHER_DATA(ctx), nbytes);
|
||||
}
|
||||
|
||||
static int
|
||||
padlock_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
|
||||
const unsigned char *in_arg, size_t nbytes)
|
||||
{
|
||||
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
|
||||
int ret;
|
||||
|
||||
memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
|
||||
if ((ret = padlock_cbc_encrypt(out_arg, in_arg, cdata, nbytes)))
|
||||
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
|
||||
const unsigned char *in_arg, size_t nbytes)
|
||||
{
|
||||
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
|
||||
size_t chunk;
|
||||
|
||||
if ((chunk = EVP_CIPHER_CTX_get_num(ctx))) { /* borrow chunk variable */
|
||||
unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
|
||||
|
||||
if (chunk >= AES_BLOCK_SIZE)
|
||||
return 0; /* bogus value */
|
||||
|
||||
if (EVP_CIPHER_CTX_is_encrypting(ctx))
|
||||
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
|
||||
ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk];
|
||||
chunk++, nbytes--;
|
||||
} else
|
||||
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
|
||||
unsigned char c = *(in_arg++);
|
||||
*(out_arg++) = c ^ ivp[chunk];
|
||||
ivp[chunk++] = c, nbytes--;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if (nbytes == 0)
|
||||
return 1;
|
||||
|
||||
memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
|
||||
|
||||
if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) {
|
||||
if (!padlock_cfb_encrypt(out_arg, in_arg, cdata, chunk))
|
||||
return 0;
|
||||
nbytes -= chunk;
|
||||
}
|
||||
|
||||
if (nbytes) {
|
||||
unsigned char *ivp = cdata->iv;
|
||||
|
||||
out_arg += chunk;
|
||||
in_arg += chunk;
|
||||
EVP_CIPHER_CTX_set_num(ctx, (int)nbytes);
|
||||
if (cdata->cword.b.encdec) {
|
||||
cdata->cword.b.encdec = 0;
|
||||
padlock_reload_key();
|
||||
padlock_aes_block(ivp, ivp, cdata);
|
||||
cdata->cword.b.encdec = 1;
|
||||
padlock_reload_key();
|
||||
while (nbytes) {
|
||||
unsigned char c = *(in_arg++);
|
||||
*(out_arg++) = c ^ *ivp;
|
||||
*(ivp++) = c, nbytes--;
|
||||
}
|
||||
} else {
|
||||
padlock_reload_key();
|
||||
padlock_aes_block(ivp, ivp, cdata);
|
||||
padlock_reload_key();
|
||||
while (nbytes) {
|
||||
*ivp = *(out_arg++) = *(in_arg++) ^ *ivp;
|
||||
ivp++, nbytes--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
|
||||
const unsigned char *in_arg, size_t nbytes)
|
||||
{
|
||||
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
|
||||
size_t chunk;
|
||||
|
||||
/*
|
||||
* ctx->num is maintained in byte-oriented modes, such as CFB and OFB...
|
||||
*/
|
||||
if ((chunk = EVP_CIPHER_CTX_get_num(ctx))) { /* borrow chunk variable */
|
||||
unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
|
||||
|
||||
if (chunk >= AES_BLOCK_SIZE)
|
||||
return 0; /* bogus value */
|
||||
|
||||
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
|
||||
*(out_arg++) = *(in_arg++) ^ ivp[chunk];
|
||||
chunk++, nbytes--;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if (nbytes == 0)
|
||||
return 1;
|
||||
|
||||
memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
|
||||
|
||||
if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) {
|
||||
if (!padlock_ofb_encrypt(out_arg, in_arg, cdata, chunk))
|
||||
return 0;
|
||||
nbytes -= chunk;
|
||||
}
|
||||
|
||||
if (nbytes) {
|
||||
unsigned char *ivp = cdata->iv;
|
||||
|
||||
out_arg += chunk;
|
||||
in_arg += chunk;
|
||||
EVP_CIPHER_CTX_set_num(ctx, (int)nbytes);
|
||||
padlock_reload_key(); /* empirically found */
|
||||
padlock_aes_block(ivp, ivp, cdata);
|
||||
padlock_reload_key(); /* empirically found */
|
||||
while (nbytes) {
|
||||
*(out_arg++) = *(in_arg++) ^ *ivp;
|
||||
ivp++, nbytes--;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void padlock_ctr32_encrypt_glue(const unsigned char *in,
|
||||
unsigned char *out, size_t blocks,
|
||||
struct padlock_cipher_data *ctx,
|
||||
const unsigned char *ivec)
|
||||
{
|
||||
memcpy(ctx->iv, ivec, AES_BLOCK_SIZE);
|
||||
padlock_ctr32_encrypt(out, in, ctx, AES_BLOCK_SIZE * blocks);
|
||||
}
|
||||
|
||||
static int
|
||||
padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
|
||||
const unsigned char *in_arg, size_t nbytes)
|
||||
{
|
||||
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
|
||||
int n = EVP_CIPHER_CTX_get_num(ctx);
|
||||
unsigned int num;
|
||||
|
||||
if (n < 0)
|
||||
return 0;
|
||||
num = (unsigned int)n;
|
||||
|
||||
CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes,
|
||||
cdata, EVP_CIPHER_CTX_iv_noconst(ctx),
|
||||
EVP_CIPHER_CTX_buf_noconst(ctx), &num,
|
||||
(ctr128_f) padlock_ctr32_encrypt_glue);
|
||||
|
||||
EVP_CIPHER_CTX_set_num(ctx, (size_t)num);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE
|
||||
# define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE
|
||||
# define EVP_CIPHER_block_size_OFB 1
|
||||
# define EVP_CIPHER_block_size_CFB 1
|
||||
# define EVP_CIPHER_block_size_CTR 1
|
||||
|
||||
/*
|
||||
* Declaring so many ciphers by hand would be a pain. Instead introduce a bit
|
||||
* of preprocessor magic :-)
|
||||
*/
|
||||
# define DECLARE_AES_EVP(ksize,lmode,umode) \
|
||||
static EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \
|
||||
static const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \
|
||||
{ \
|
||||
if (_hidden_aes_##ksize##_##lmode == NULL \
|
||||
&& ((_hidden_aes_##ksize##_##lmode = \
|
||||
EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode, \
|
||||
EVP_CIPHER_block_size_##umode, \
|
||||
AES_KEY_SIZE_##ksize)) == NULL \
|
||||
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_##ksize##_##lmode, \
|
||||
AES_BLOCK_SIZE) \
|
||||
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_##ksize##_##lmode, \
|
||||
0 | EVP_CIPH_##umode##_MODE) \
|
||||
|| !EVP_CIPHER_meth_set_init(_hidden_aes_##ksize##_##lmode, \
|
||||
padlock_aes_init_key) \
|
||||
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_##ksize##_##lmode, \
|
||||
padlock_##lmode##_cipher) \
|
||||
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_##ksize##_##lmode, \
|
||||
sizeof(struct padlock_cipher_data) + 16) \
|
||||
|| !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_##ksize##_##lmode, \
|
||||
EVP_CIPHER_set_asn1_iv) \
|
||||
|| !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_##ksize##_##lmode, \
|
||||
EVP_CIPHER_get_asn1_iv))) { \
|
||||
EVP_CIPHER_meth_free(_hidden_aes_##ksize##_##lmode); \
|
||||
_hidden_aes_##ksize##_##lmode = NULL; \
|
||||
} \
|
||||
return _hidden_aes_##ksize##_##lmode; \
|
||||
}
|
||||
|
||||
DECLARE_AES_EVP(128, ecb, ECB)
|
||||
DECLARE_AES_EVP(128, cbc, CBC)
|
||||
DECLARE_AES_EVP(128, cfb, CFB)
|
||||
DECLARE_AES_EVP(128, ofb, OFB)
|
||||
DECLARE_AES_EVP(128, ctr, CTR)
|
||||
|
||||
DECLARE_AES_EVP(192, ecb, ECB)
|
||||
DECLARE_AES_EVP(192, cbc, CBC)
|
||||
DECLARE_AES_EVP(192, cfb, CFB)
|
||||
DECLARE_AES_EVP(192, ofb, OFB)
|
||||
DECLARE_AES_EVP(192, ctr, CTR)
|
||||
|
||||
DECLARE_AES_EVP(256, ecb, ECB)
|
||||
DECLARE_AES_EVP(256, cbc, CBC)
|
||||
DECLARE_AES_EVP(256, cfb, CFB)
|
||||
DECLARE_AES_EVP(256, ofb, OFB)
|
||||
DECLARE_AES_EVP(256, ctr, CTR)
|
||||
|
||||
static int
|
||||
padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids,
|
||||
int nid)
|
||||
{
|
||||
/* No specific cipher => return a list of supported nids ... */
|
||||
if (!cipher) {
|
||||
*nids = padlock_cipher_nids;
|
||||
return padlock_cipher_nids_num;
|
||||
}
|
||||
|
||||
/* ... or the requested "cipher" otherwise */
|
||||
switch (nid) {
|
||||
case NID_aes_128_ecb:
|
||||
*cipher = padlock_aes_128_ecb();
|
||||
break;
|
||||
case NID_aes_128_cbc:
|
||||
*cipher = padlock_aes_128_cbc();
|
||||
break;
|
||||
case NID_aes_128_cfb:
|
||||
*cipher = padlock_aes_128_cfb();
|
||||
break;
|
||||
case NID_aes_128_ofb:
|
||||
*cipher = padlock_aes_128_ofb();
|
||||
break;
|
||||
case NID_aes_128_ctr:
|
||||
*cipher = padlock_aes_128_ctr();
|
||||
break;
|
||||
|
||||
case NID_aes_192_ecb:
|
||||
*cipher = padlock_aes_192_ecb();
|
||||
break;
|
||||
case NID_aes_192_cbc:
|
||||
*cipher = padlock_aes_192_cbc();
|
||||
break;
|
||||
case NID_aes_192_cfb:
|
||||
*cipher = padlock_aes_192_cfb();
|
||||
break;
|
||||
case NID_aes_192_ofb:
|
||||
*cipher = padlock_aes_192_ofb();
|
||||
break;
|
||||
case NID_aes_192_ctr:
|
||||
*cipher = padlock_aes_192_ctr();
|
||||
break;
|
||||
|
||||
case NID_aes_256_ecb:
|
||||
*cipher = padlock_aes_256_ecb();
|
||||
break;
|
||||
case NID_aes_256_cbc:
|
||||
*cipher = padlock_aes_256_cbc();
|
||||
break;
|
||||
case NID_aes_256_cfb:
|
||||
*cipher = padlock_aes_256_cfb();
|
||||
break;
|
||||
case NID_aes_256_ofb:
|
||||
*cipher = padlock_aes_256_ofb();
|
||||
break;
|
||||
case NID_aes_256_ctr:
|
||||
*cipher = padlock_aes_256_ctr();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Sorry, we don't support this NID */
|
||||
*cipher = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Prepare the encryption key for PadLock usage */
|
||||
static int
|
||||
padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
struct padlock_cipher_data *cdata;
|
||||
int key_len = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
|
||||
unsigned long mode = EVP_CIPHER_CTX_get_mode(ctx);
|
||||
|
||||
if (key == NULL)
|
||||
return 0; /* ERROR */
|
||||
|
||||
cdata = ALIGNED_CIPHER_DATA(ctx);
|
||||
memset(cdata, 0, sizeof(*cdata));
|
||||
|
||||
/* Prepare Control word. */
|
||||
if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE)
|
||||
cdata->cword.b.encdec = 0;
|
||||
else
|
||||
cdata->cword.b.encdec = (EVP_CIPHER_CTX_is_encrypting(ctx) == 0);
|
||||
cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
|
||||
cdata->cword.b.ksize = (key_len - 128) / 64;
|
||||
|
||||
switch (key_len) {
|
||||
case 128:
|
||||
/*
|
||||
* PadLock can generate an extended key for AES128 in hardware
|
||||
*/
|
||||
memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128);
|
||||
cdata->cword.b.keygen = 0;
|
||||
break;
|
||||
|
||||
case 192:
|
||||
case 256:
|
||||
/*
|
||||
* Generate an extended AES key in software. Needed for AES192/AES256
|
||||
*/
|
||||
/*
|
||||
* Well, the above applies to Stepping 8 CPUs and is listed as
|
||||
* hardware errata. They most likely will fix it at some point and
|
||||
* then a check for stepping would be due here.
|
||||
*/
|
||||
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
|
||||
&& !enc)
|
||||
AES_set_decrypt_key(key, key_len, &cdata->ks);
|
||||
else
|
||||
AES_set_encrypt_key(key, key_len, &cdata->ks);
|
||||
/*
|
||||
* OpenSSL C functions use byte-swapped extended key.
|
||||
*/
|
||||
padlock_key_bswap(&cdata->ks);
|
||||
cdata->cword.b.keygen = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ERROR */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is done to cover for cases when user reuses the
|
||||
* context for new key. The catch is that if we don't do
|
||||
* this, padlock_eas_cipher might proceed with old key...
|
||||
*/
|
||||
padlock_reload_key();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ===== Random Number Generator ===== */
|
||||
/*
|
||||
* This code is not engaged. The reason is that it does not comply
|
||||
* with recommendations for VIA RNG usage for secure applications
|
||||
* (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
|
||||
* provide meaningful error control...
|
||||
*/
|
||||
/*
|
||||
* Wrapper that provides an interface between the API and the raw PadLock
|
||||
* RNG
|
||||
*/
|
||||
static int padlock_rand_bytes(unsigned char *output, int count)
|
||||
{
|
||||
unsigned int eax, buf;
|
||||
|
||||
while (count >= 8) {
|
||||
eax = padlock_xstore(output, 0);
|
||||
if (!(eax & (1 << 6)))
|
||||
return 0; /* RNG disabled */
|
||||
/* this ---vv--- covers DC bias, Raw Bits and String Filter */
|
||||
if (eax & (0x1F << 10))
|
||||
return 0;
|
||||
if ((eax & 0x1F) == 0)
|
||||
continue; /* no data, retry... */
|
||||
if ((eax & 0x1F) != 8)
|
||||
return 0; /* fatal failure... */
|
||||
output += 8;
|
||||
count -= 8;
|
||||
}
|
||||
while (count > 0) {
|
||||
eax = padlock_xstore(&buf, 3);
|
||||
if (!(eax & (1 << 6)))
|
||||
return 0; /* RNG disabled */
|
||||
/* this ---vv--- covers DC bias, Raw Bits and String Filter */
|
||||
if (eax & (0x1F << 10))
|
||||
return 0;
|
||||
if ((eax & 0x1F) == 0)
|
||||
continue; /* no data, retry... */
|
||||
if ((eax & 0x1F) != 1)
|
||||
return 0; /* fatal failure... */
|
||||
*output++ = (unsigned char)buf;
|
||||
count--;
|
||||
}
|
||||
OPENSSL_cleanse(&buf, sizeof(buf));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Dummy but necessary function */
|
||||
static int padlock_rand_status(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Prepare structure for registration */
|
||||
static RAND_METHOD padlock_rand = {
|
||||
NULL, /* seed */
|
||||
padlock_rand_bytes, /* bytes */
|
||||
NULL, /* cleanup */
|
||||
NULL, /* add */
|
||||
padlock_rand_bytes, /* pseudorand */
|
||||
padlock_rand_status, /* rand status */
|
||||
};
|
||||
|
||||
# endif /* COMPILE_PADLOCKENG */
|
||||
#endif /* !OPENSSL_NO_PADLOCKENG */
|
||||
Reference in New Issue
Block a user