( 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;
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';
}
IF[{- !$disabled{demos} -}]
SUBDIRS=demos
ENDIF
-IF[{- !$disabled{'deprecated-3.0'} -}]
- SUBDIRS=engines
-ENDIF
SUBDIRS=exporters
LIBS=libcrypto libssl
+++ /dev/null
-#! /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;
+++ /dev/null
-#! /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;
+++ /dev/null
-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
+++ /dev/null
-/*
- * 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 */
+++ /dev/null
-# The INPUT HEADER is scanned for declarations
-# LIBNAME INPUT HEADER ERROR-TABLE FILE
-L AFALG e_afalg_err.h e_afalg_err.c
+++ /dev/null
-/*
- * 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
+++ /dev/null
-# 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
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * Copyright 2008-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
-
-#ifdef _WIN32
-# ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0400
-# endif
-# include <windows.h>
-# include <wincrypt.h>
-
-# include <stdio.h>
-# include <string.h>
-# include <stdlib.h>
-# include <malloc.h>
-# ifndef alloca
-# define alloca _alloca
-# endif
-
-# include <openssl/crypto.h>
-
-# ifndef OPENSSL_NO_CAPIENG
-
-# include <openssl/buffer.h>
-# include <openssl/bn.h>
-# include <openssl/rsa.h>
-# include <openssl/dsa.h>
-
-/*
- * This module uses several "new" interfaces, among which is
- * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is
- * one of possible values you can pass to function in question. By
- * checking if it's defined we can see if wincrypt.h and accompanying
- * crypt32.lib are in shape. The native MingW32 headers up to and
- * including __W32API_VERSION 3.14 lack of struct DSSPUBKEY and the
- * defines CERT_STORE_PROV_SYSTEM_A and CERT_STORE_READONLY_FLAG,
- * so we check for these too and avoid compiling.
- * Yes, it's rather "weak" test and if compilation fails,
- * then re-configure with -DOPENSSL_NO_CAPIENG.
- */
-# if defined(CERT_KEY_PROV_INFO_PROP_ID) && \
- defined(CERT_STORE_PROV_SYSTEM_A) && \
- defined(CERT_STORE_READONLY_FLAG)
-# define __COMPILE_CAPIENG
-# endif /* CERT_KEY_PROV_INFO_PROP_ID */
-# endif /* OPENSSL_NO_CAPIENG */
-#endif /* _WIN32 */
-
-#ifdef __COMPILE_CAPIENG
-
-# undef X509_EXTENSIONS
-
-/* Definitions which may be missing from earlier version of headers */
-# ifndef CERT_STORE_OPEN_EXISTING_FLAG
-# define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
-# endif
-
-# ifndef CERT_STORE_CREATE_NEW_FLAG
-# define CERT_STORE_CREATE_NEW_FLAG 0x00002000
-# endif
-
-# ifndef CERT_SYSTEM_STORE_CURRENT_USER
-# define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000
-# endif
-
-# ifndef ALG_SID_SHA_256
-# define ALG_SID_SHA_256 12
-# endif
-# ifndef ALG_SID_SHA_384
-# define ALG_SID_SHA_384 13
-# endif
-# ifndef ALG_SID_SHA_512
-# define ALG_SID_SHA_512 14
-# endif
-
-# ifndef CALG_SHA_256
-# define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
-# endif
-# ifndef CALG_SHA_384
-# define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384)
-# endif
-# ifndef CALG_SHA_512
-# define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512)
-# endif
-
-# ifndef PROV_RSA_AES
-# define PROV_RSA_AES 24
-# endif
-
-# include <openssl/engine.h>
-# include <openssl/pem.h>
-# include <openssl/x509v3.h>
-
-/* clang-format off */
-# include "e_capi_err.h"
-# include "e_capi_err.c"
-/* clang-format on */
-
-static const char *engine_capi_id = "capi";
-static const char *engine_capi_name = "CryptoAPI ENGINE";
-
-typedef struct CAPI_CTX_st CAPI_CTX;
-typedef struct CAPI_KEY_st CAPI_KEY;
-
-static void capi_addlasterror(void);
-static void capi_adderror(DWORD err);
-
-static void CAPI_trace(CAPI_CTX *ctx, char *format, ...);
-
-static int capi_list_providers(CAPI_CTX *ctx, BIO *out);
-static int capi_list_containers(CAPI_CTX *ctx, BIO *out);
-int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *storename);
-void capi_free_key(CAPI_KEY *key);
-
-static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id,
- HCERTSTORE hstore);
-
-CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id);
-
-static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
- UI_METHOD *ui_method, void *callback_data);
-static int capi_rsa_sign(int dtype, const unsigned char *m,
- unsigned int m_len, unsigned char *sigret,
- unsigned int *siglen, const RSA *rsa);
-static int capi_rsa_priv_enc(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-static int capi_rsa_priv_dec(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-static int capi_rsa_free(RSA *rsa);
-
-# ifndef OPENSSL_NO_DSA
-static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
- DSA *dsa);
-static int capi_dsa_free(DSA *dsa);
-# endif
-
-static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
- STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
- EVP_PKEY **pkey, STACK_OF(X509) **pother,
- UI_METHOD *ui_method,
- void *callback_data);
-
-static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
-# ifdef OPENSSL_CAPIENG_DIALOG
-static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
-# endif
-
-void engine_load_capi_int(void);
-
-typedef PCCERT_CONTEXT(WINAPI *CERTDLG)(HCERTSTORE, HWND, LPCWSTR,
- LPCWSTR, DWORD, DWORD, void *);
-typedef HWND(WINAPI *GETCONSWIN)(void);
-
-/*
- * This structure contains CAPI ENGINE specific data: it contains various
- * global options and affects how other functions behave.
- */
-
-# define CAPI_DBG_TRACE 2
-# define CAPI_DBG_ERROR 1
-
-struct CAPI_CTX_st {
- int debug_level;
- char *debug_file;
- /* Parameters to use for container lookup */
- DWORD keytype;
- LPSTR cspname;
- DWORD csptype;
- /* Certificate store name to use */
- LPSTR storename;
- LPSTR ssl_client_store;
- /* System store flags */
- DWORD store_flags;
-/* Lookup string meanings in load_private_key */
-# define CAPI_LU_SUBSTR 1 /* Substring of subject: uses "storename" */
-# define CAPI_LU_FNAME 2 /* Friendly name: uses storename */
-# define CAPI_LU_CONTNAME 3 /* Container name: uses cspname, keytype */
- int lookup_method;
-/* Info to dump with dumpcerts option */
-# define CAPI_DMP_SUMMARY 0x1 /* Issuer and serial name strings */
-# define CAPI_DMP_FNAME 0x2 /* Friendly name */
-# define CAPI_DMP_FULL 0x4 /* Full X509_print dump */
-# define CAPI_DMP_PEM 0x8 /* Dump PEM format certificate */
-# define CAPI_DMP_PSKEY 0x10 /* Dump pseudo key (if possible) */
-# define CAPI_DMP_PKEYINFO 0x20 /* Dump key info (if possible) */
- DWORD dump_flags;
- int (*client_cert_select) (ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
- CERTDLG certselectdlg;
- GETCONSWIN getconswindow;
-};
-
-static CAPI_CTX *capi_ctx_new(void);
-static void capi_ctx_free(CAPI_CTX *ctx);
-static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type,
- int check);
-static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx);
-
-# define CAPI_CMD_LIST_CERTS ENGINE_CMD_BASE
-# define CAPI_CMD_LOOKUP_CERT (ENGINE_CMD_BASE + 1)
-# define CAPI_CMD_DEBUG_LEVEL (ENGINE_CMD_BASE + 2)
-# define CAPI_CMD_DEBUG_FILE (ENGINE_CMD_BASE + 3)
-# define CAPI_CMD_KEYTYPE (ENGINE_CMD_BASE + 4)
-# define CAPI_CMD_LIST_CSPS (ENGINE_CMD_BASE + 5)
-# define CAPI_CMD_SET_CSP_IDX (ENGINE_CMD_BASE + 6)
-# define CAPI_CMD_SET_CSP_NAME (ENGINE_CMD_BASE + 7)
-# define CAPI_CMD_SET_CSP_TYPE (ENGINE_CMD_BASE + 8)
-# define CAPI_CMD_LIST_CONTAINERS (ENGINE_CMD_BASE + 9)
-# define CAPI_CMD_LIST_OPTIONS (ENGINE_CMD_BASE + 10)
-# define CAPI_CMD_LOOKUP_METHOD (ENGINE_CMD_BASE + 11)
-# define CAPI_CMD_STORE_NAME (ENGINE_CMD_BASE + 12)
-# define CAPI_CMD_STORE_FLAGS (ENGINE_CMD_BASE + 13)
-
-static const ENGINE_CMD_DEFN capi_cmd_defns[] = {
- {CAPI_CMD_LIST_CERTS,
- "list_certs",
- "List all certificates in store",
- ENGINE_CMD_FLAG_NO_INPUT},
- {CAPI_CMD_LOOKUP_CERT,
- "lookup_cert",
- "Lookup and output certificates",
- ENGINE_CMD_FLAG_STRING},
- {CAPI_CMD_DEBUG_LEVEL,
- "debug_level",
- "debug level (1=errors, 2=trace)",
- ENGINE_CMD_FLAG_NUMERIC},
- {CAPI_CMD_DEBUG_FILE,
- "debug_file",
- "debugging filename)",
- ENGINE_CMD_FLAG_STRING},
- {CAPI_CMD_KEYTYPE,
- "key_type",
- "Key type: 1=AT_KEYEXCHANGE (default), 2=AT_SIGNATURE",
- ENGINE_CMD_FLAG_NUMERIC},
- {CAPI_CMD_LIST_CSPS,
- "list_csps",
- "List all CSPs",
- ENGINE_CMD_FLAG_NO_INPUT},
- {CAPI_CMD_SET_CSP_IDX,
- "csp_idx",
- "Set CSP by index",
- ENGINE_CMD_FLAG_NUMERIC},
- {CAPI_CMD_SET_CSP_NAME,
- "csp_name",
- "Set CSP name, (default CSP used if not specified)",
- ENGINE_CMD_FLAG_STRING},
- {CAPI_CMD_SET_CSP_TYPE,
- "csp_type",
- "Set CSP type, (default RSA_PROV_FULL)",
- ENGINE_CMD_FLAG_NUMERIC},
- {CAPI_CMD_LIST_CONTAINERS,
- "list_containers",
- "list container names",
- ENGINE_CMD_FLAG_NO_INPUT},
- {CAPI_CMD_LIST_OPTIONS,
- "list_options",
- "Set list options (1=summary,2=friendly name, 4=full printout, 8=PEM output, 16=XXX, "
- "32=private key info)",
- ENGINE_CMD_FLAG_NUMERIC},
- {CAPI_CMD_LOOKUP_METHOD,
- "lookup_method",
- "Set key lookup method (1=substring, 2=friendlyname, 3=container name)",
- ENGINE_CMD_FLAG_NUMERIC},
- {CAPI_CMD_STORE_NAME,
- "store_name",
- "certificate store name, default \"MY\"",
- ENGINE_CMD_FLAG_STRING},
- {CAPI_CMD_STORE_FLAGS,
- "store_flags",
- "Certificate store flags: 1 = system store",
- ENGINE_CMD_FLAG_NUMERIC},
-
- {0, NULL, NULL, 0}
-};
-
-static int capi_idx = -1;
-static int rsa_capi_idx = -1;
-static int dsa_capi_idx = -1;
-static int cert_capi_idx = -1;
-
-static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
-{
- int ret = 1;
- CAPI_CTX *ctx;
- BIO *out;
- LPSTR tmpstr;
- if (capi_idx == -1) {
- CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED);
- return 0;
- }
- ctx = ENGINE_get_ex_data(e, capi_idx);
- out = BIO_new_fp(stdout, BIO_NOCLOSE);
- if (out == NULL) {
- CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_FILE_OPEN_ERROR);
- return 0;
- }
- switch (cmd) {
- case CAPI_CMD_LIST_CSPS:
- ret = capi_list_providers(ctx, out);
- break;
-
- case CAPI_CMD_LIST_CERTS:
- ret = capi_list_certs(ctx, out, NULL);
- break;
-
- case CAPI_CMD_LOOKUP_CERT:
- ret = capi_list_certs(ctx, out, p);
- break;
-
- case CAPI_CMD_LIST_CONTAINERS:
- ret = capi_list_containers(ctx, out);
- break;
-
- case CAPI_CMD_STORE_NAME:
- tmpstr = OPENSSL_strdup(p);
- if (tmpstr != NULL) {
- OPENSSL_free(ctx->storename);
- ctx->storename = tmpstr;
- CAPI_trace(ctx, "Setting store name to %s\n", p);
- } else {
- ret = 0;
- }
- break;
-
- case CAPI_CMD_STORE_FLAGS:
- if (i & 1) {
- ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
- ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
- } else {
- ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER;
- ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE;
- }
- CAPI_trace(ctx, "Setting flags to %d\n", i);
- break;
-
- case CAPI_CMD_DEBUG_LEVEL:
- ctx->debug_level = (int)i;
- CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level);
- break;
-
- case CAPI_CMD_DEBUG_FILE:
- tmpstr = OPENSSL_strdup(p);
- if (tmpstr != NULL) {
- ctx->debug_file = tmpstr;
- CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file);
- } else {
- ret = 0;
- }
- break;
-
- case CAPI_CMD_KEYTYPE:
- ctx->keytype = i;
- CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype);
- break;
-
- case CAPI_CMD_SET_CSP_IDX:
- ret = capi_ctx_set_provname_idx(ctx, i);
- break;
-
- case CAPI_CMD_LIST_OPTIONS:
- ctx->dump_flags = i;
- break;
-
- case CAPI_CMD_LOOKUP_METHOD:
- if (i < 1 || i > 3) {
- CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD);
- BIO_free(out);
- return 0;
- }
- ctx->lookup_method = i;
- break;
-
- case CAPI_CMD_SET_CSP_NAME:
- ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1);
- break;
-
- case CAPI_CMD_SET_CSP_TYPE:
- ctx->csptype = i;
- break;
-
- default:
- CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND);
- ret = 0;
- }
-
- BIO_free(out);
- return ret;
-
-}
-
-static RSA_METHOD *capi_rsa_method = NULL;
-# ifndef OPENSSL_NO_DSA
-static DSA_METHOD *capi_dsa_method = NULL;
-# endif
-
-static int use_aes_csp = 0;
-static const WCHAR rsa_aes_cspname[] =
- L"Microsoft Enhanced RSA and AES Cryptographic Provider";
-static const WCHAR rsa_enh_cspname[] =
- L"Microsoft Enhanced Cryptographic Provider v1.0";
-
-static int capi_init(ENGINE *e)
-{
- CAPI_CTX *ctx;
- const RSA_METHOD *ossl_rsa_meth;
-# ifndef OPENSSL_NO_DSA
- const DSA_METHOD *ossl_dsa_meth;
-# endif
- HCRYPTPROV hprov;
-
- if (capi_idx < 0) {
- capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
- if (capi_idx < 0) {
- CAPIerr(CAPI_F_CAPI_INIT, ERR_R_ENGINE_LIB);
- goto err;
- }
-
- cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0);
-
- /* Setup RSA_METHOD */
- rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
- ossl_rsa_meth = RSA_PKCS1_OpenSSL();
- if (!RSA_meth_set_pub_enc(capi_rsa_method,
- RSA_meth_get_pub_enc(ossl_rsa_meth))
- || !RSA_meth_set_pub_dec(capi_rsa_method,
- RSA_meth_get_pub_dec(ossl_rsa_meth))
- || !RSA_meth_set_priv_enc(capi_rsa_method, capi_rsa_priv_enc)
- || !RSA_meth_set_priv_dec(capi_rsa_method, capi_rsa_priv_dec)
- || !RSA_meth_set_mod_exp(capi_rsa_method,
- RSA_meth_get_mod_exp(ossl_rsa_meth))
- || !RSA_meth_set_bn_mod_exp(capi_rsa_method,
- RSA_meth_get_bn_mod_exp(ossl_rsa_meth))
- || !RSA_meth_set_finish(capi_rsa_method, capi_rsa_free)
- || !RSA_meth_set_sign(capi_rsa_method, capi_rsa_sign)) {
- CAPIerr(CAPI_F_CAPI_INIT, ERR_R_RSA_LIB);
- goto err;
- }
-
-# ifndef OPENSSL_NO_DSA
- /* Setup DSA Method */
- dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
- ossl_dsa_meth = DSA_OpenSSL();
- if (!DSA_meth_set_sign(capi_dsa_method, capi_dsa_do_sign)
- || !DSA_meth_set_verify(capi_dsa_method,
- DSA_meth_get_verify(ossl_dsa_meth))
- || !DSA_meth_set_finish(capi_dsa_method, capi_dsa_free)
- || !DSA_meth_set_mod_exp(capi_dsa_method,
- DSA_meth_get_mod_exp(ossl_dsa_meth))
- || !DSA_meth_set_bn_mod_exp(capi_dsa_method,
- DSA_meth_get_bn_mod_exp(ossl_dsa_meth))) {
- CAPIerr(CAPI_F_CAPI_INIT, ERR_R_DSA_LIB);
- goto err;
- }
-# endif
- }
-
- ctx = capi_ctx_new();
- if (ctx == NULL) {
- CAPIerr(CAPI_F_CAPI_INIT, ERR_R_CAPI_LIB);
- goto err;
- }
-
- ENGINE_set_ex_data(e, capi_idx, ctx);
-
-# ifdef OPENSSL_CAPIENG_DIALOG
- {
- HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL"));
- HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL"));
- if (cryptui)
- ctx->certselectdlg =
- (CERTDLG) GetProcAddress(cryptui,
- "CryptUIDlgSelectCertificateFromStore");
- if (kernel)
- ctx->getconswindow =
- (GETCONSWIN) GetProcAddress(kernel, "GetConsoleWindow");
- if (cryptui && !OPENSSL_isservice())
- ctx->client_cert_select = cert_select_dialog;
- }
-# endif
-
- /* See if there is RSA+AES CSP */
- if (CryptAcquireContextW(&hprov, NULL, rsa_aes_cspname, PROV_RSA_AES,
- CRYPT_VERIFYCONTEXT)) {
- use_aes_csp = 1;
- CryptReleaseContext(hprov, 0);
- }
-
- return 1;
-
- err:
- return 0;
-}
-
-static int capi_destroy(ENGINE *e)
-{
- RSA_meth_free(capi_rsa_method);
- capi_rsa_method = NULL;
-# ifndef OPENSSL_NO_DSA
- DSA_meth_free(capi_dsa_method);
- capi_dsa_method = NULL;
-# endif
- ERR_unload_CAPI_strings();
- return 1;
-}
-
-static int capi_finish(ENGINE *e)
-{
- CAPI_CTX *ctx;
- ctx = ENGINE_get_ex_data(e, capi_idx);
- capi_ctx_free(ctx);
- ENGINE_set_ex_data(e, capi_idx, NULL);
- return 1;
-}
-
-/*
- * CryptoAPI key application data. This contains a handle to the private key
- * container (for sign operations) and a handle to the key (for decrypt
- * operations).
- */
-
-struct CAPI_KEY_st {
- /* Associated certificate context (if any) */
- PCCERT_CONTEXT pcert;
- HCRYPTPROV hprov;
- HCRYPTKEY key;
- DWORD keyspec;
-};
-
-static int bind_capi(ENGINE *e)
-{
- capi_rsa_method = RSA_meth_new("CryptoAPI RSA method", 0);
- if (capi_rsa_method == NULL)
- return 0;
-# ifndef OPENSSL_NO_DSA
- capi_dsa_method = DSA_meth_new("CryptoAPI DSA method", 0);
- if (capi_dsa_method == NULL)
- goto memerr;
-# endif
- if (!ENGINE_set_id(e, engine_capi_id)
- || !ENGINE_set_name(e, engine_capi_name)
- || !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL)
- || !ENGINE_set_init_function(e, capi_init)
- || !ENGINE_set_finish_function(e, capi_finish)
- || !ENGINE_set_destroy_function(e, capi_destroy)
- || !ENGINE_set_RSA(e, capi_rsa_method)
-# ifndef OPENSSL_NO_DSA
- || !ENGINE_set_DSA(e, capi_dsa_method)
-# endif
- || !ENGINE_set_load_privkey_function(e, capi_load_privkey)
- || !ENGINE_set_load_ssl_client_cert_function(e,
- capi_load_ssl_client_cert)
- || !ENGINE_set_cmd_defns(e, capi_cmd_defns)
- || !ENGINE_set_ctrl_function(e, capi_ctrl))
- goto memerr;
- ERR_load_CAPI_strings();
-
- return 1;
- memerr:
- RSA_meth_free(capi_rsa_method);
- capi_rsa_method = NULL;
-# ifndef OPENSSL_NO_DSA
- DSA_meth_free(capi_dsa_method);
- capi_dsa_method = NULL;
-# endif
- return 0;
-}
-
-static ENGINE *engine_capi(void)
-{
- ENGINE *ret = ENGINE_new();
- if (ret == NULL)
- return NULL;
- if (!bind_capi(ret)) {
- ENGINE_free(ret);
- return NULL;
- }
- return ret;
-}
-
-void engine_load_capi_int(void)
-{
- /* Copied from eng_[openssl|dyn].c */
- ENGINE *toadd = engine_capi();
- 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 lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen)
-{
- int i;
- /*
- * Reverse buffer in place: since this is a keyblob structure that will
- * be freed up after conversion anyway it doesn't matter if we change
- * it.
- */
- for (i = 0; i < binlen / 2; i++) {
- unsigned char c;
- c = bin[i];
- bin[i] = bin[binlen - i - 1];
- bin[binlen - i - 1] = c;
- }
-
- if (!BN_bin2bn(bin, binlen, bn))
- return 0;
- return 1;
-}
-
-/* Given a CAPI_KEY get an EVP_PKEY structure */
-
-static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key)
-{
- unsigned char *pubkey = NULL;
- DWORD len;
- BLOBHEADER *bh;
- RSA *rkey = NULL;
- DSA *dkey = NULL;
- EVP_PKEY *ret = NULL;
- if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR);
- capi_addlasterror();
- return NULL;
- }
-
- pubkey = OPENSSL_malloc(len);
-
- if (pubkey == NULL)
- goto err;
-
- if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR);
- capi_addlasterror();
- goto err;
- }
-
- bh = (BLOBHEADER *) pubkey;
- if (bh->bType != PUBLICKEYBLOB) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB);
- goto err;
- }
- if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) {
- RSAPUBKEY *rp;
- DWORD rsa_modlen;
- BIGNUM *e = NULL, *n = NULL;
- unsigned char *rsa_modulus;
- rp = (RSAPUBKEY *) (bh + 1);
- if (rp->magic != 0x31415352) {
- char magstr[10];
- BIO_snprintf(magstr, 10, "%lx", rp->magic);
- CAPIerr(CAPI_F_CAPI_GET_PKEY,
- CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
- ERR_add_error_data(2, "magic=0x", magstr);
- goto err;
- }
- rsa_modulus = (unsigned char *)(rp + 1);
- rkey = RSA_new_method(eng);
- if (!rkey) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_RSA_LIB);
- goto err;
- }
-
- e = BN_new();
- n = BN_new();
-
- if (e == NULL || n == NULL) {
- BN_free(e);
- BN_free(n);
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_BN_LIB);
- goto err;
- }
-
- RSA_set0_key(rkey, n, e, NULL);
-
- if (!BN_set_word(e, rp->pubexp)) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_BN_LIB);
- goto err;
- }
-
- rsa_modlen = rp->bitlen / 8;
- if (!lend_tobn(n, rsa_modulus, rsa_modlen)) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_BN_LIB);
- goto err;
- }
-
- RSA_set_ex_data(rkey, rsa_capi_idx, key);
-
- if ((ret = EVP_PKEY_new()) == NULL) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_EVP_LIB);
- goto err;
- }
-
- EVP_PKEY_assign_RSA(ret, rkey);
- rkey = NULL;
-
-# ifndef OPENSSL_NO_DSA
- } else if (bh->aiKeyAlg == CALG_DSS_SIGN) {
- DSSPUBKEY *dp;
- DWORD dsa_plen;
- unsigned char *btmp;
- BIGNUM *p, *q, *g, *pub_key;
- dp = (DSSPUBKEY *) (bh + 1);
- if (dp->magic != 0x31535344) {
- char magstr[10];
- BIO_snprintf(magstr, 10, "%lx", dp->magic);
- CAPIerr(CAPI_F_CAPI_GET_PKEY,
- CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
- ERR_add_error_data(2, "magic=0x", magstr);
- goto err;
- }
- dsa_plen = dp->bitlen / 8;
- btmp = (unsigned char *)(dp + 1);
- dkey = DSA_new_method(eng);
- if (!dkey) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_DSA_LIB);
- goto err;
- }
- p = BN_new();
- q = BN_new();
- g = BN_new();
- pub_key = BN_new();
- if (p == NULL || q == NULL || g == NULL || pub_key == NULL) {
- BN_free(p);
- BN_free(q);
- BN_free(g);
- BN_free(pub_key);
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_BN_LIB);
- goto err;
- }
- DSA_set0_pqg(dkey, p, q, g);
- DSA_set0_key(dkey, pub_key, NULL);
- if (!lend_tobn(p, btmp, dsa_plen)) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_CAPI_LIB);
- goto err;
- }
- btmp += dsa_plen;
- if (!lend_tobn(q, btmp, 20)) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_CAPI_LIB);
- goto err;
- }
- btmp += 20;
- if (!lend_tobn(g, btmp, dsa_plen)) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_CAPI_LIB);
- goto err;
- }
- btmp += dsa_plen;
- if (!lend_tobn(pub_key, btmp, dsa_plen)) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_CAPI_LIB);
- goto err;
- }
- btmp += dsa_plen;
-
- DSA_set_ex_data(dkey, dsa_capi_idx, key);
-
- if ((ret = EVP_PKEY_new()) == NULL) {
- CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_EVP_LIB);
- goto err;
- }
-
- EVP_PKEY_assign_DSA(ret, dkey);
- dkey = NULL;
-# endif
- } else {
- char algstr[10];
- BIO_snprintf(algstr, 10, "%ux", bh->aiKeyAlg);
- CAPIerr(CAPI_F_CAPI_GET_PKEY,
- CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM);
- ERR_add_error_data(2, "aiKeyAlg=0x", algstr);
- goto err;
- }
-
- err:
- OPENSSL_free(pubkey);
- if (!ret) {
- RSA_free(rkey);
-# ifndef OPENSSL_NO_DSA
- DSA_free(dkey);
-# endif
- }
-
- return ret;
-}
-
-static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
- UI_METHOD *ui_method, void *callback_data)
-{
- CAPI_CTX *ctx;
- CAPI_KEY *key;
- EVP_PKEY *ret;
- ctx = ENGINE_get_ex_data(eng, capi_idx);
-
- if (!ctx) {
- CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT);
- return NULL;
- }
-
- key = capi_find_key(ctx, key_id);
-
- if (!key)
- return NULL;
-
- ret = capi_get_pkey(eng, key);
-
- if (!ret)
- capi_free_key(key);
- return ret;
-
-}
-
-/* CryptoAPI RSA operations */
-
-int capi_rsa_priv_enc(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding)
-{
- CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED);
- return -1;
-}
-
-int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
- unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
-{
- ALG_ID alg;
- HCRYPTHASH hash;
- DWORD slen;
- unsigned int i;
- int ret = -1;
- CAPI_KEY *capi_key;
- CAPI_CTX *ctx;
-
- ctx = ENGINE_get_ex_data(RSA_get0_engine(rsa), capi_idx);
-
- CAPI_trace(ctx, "Called CAPI_rsa_sign()\n");
-
- capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
- if (!capi_key) {
- CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY);
- return -1;
- }
- /* Convert the signature type to a CryptoAPI algorithm ID */
- switch (dtype) {
- case NID_sha256:
- alg = CALG_SHA_256;
- break;
-
- case NID_sha384:
- alg = CALG_SHA_384;
- break;
-
- case NID_sha512:
- alg = CALG_SHA_512;
- break;
-
- case NID_sha1:
- alg = CALG_SHA1;
- break;
-
- case NID_md5:
- alg = CALG_MD5;
- break;
-
- case NID_md5_sha1:
- alg = CALG_SSL3_SHAMD5;
- break;
- default:
- {
- char algstr[10];
- BIO_snprintf(algstr, 10, "%x", dtype);
- CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID);
- ERR_add_error_data(2, "NID=0x", algstr);
- return -1;
- }
- }
-
- /* Create the hash object */
- if (!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) {
- CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
- capi_addlasterror();
- return -1;
- }
- /* Set the hash value to the value passed */
-
- if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) {
- CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
- capi_addlasterror();
- goto err;
- }
-
- /* Finally sign it */
- slen = RSA_size(rsa);
- if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) {
- CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH);
- capi_addlasterror();
- goto err;
- } else {
- ret = 1;
- /* Inplace byte reversal of signature */
- for (i = 0; i < slen / 2; i++) {
- unsigned char c;
- c = sigret[i];
- sigret[i] = sigret[slen - i - 1];
- sigret[slen - i - 1] = c;
- }
- *siglen = slen;
- }
-
- /* Now cleanup */
-
- err:
- CryptDestroyHash(hash);
-
- return ret;
-}
-
-int capi_rsa_priv_dec(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding)
-{
- int i;
- unsigned char *tmpbuf;
- CAPI_KEY *capi_key;
- CAPI_CTX *ctx;
- DWORD flags = 0;
- DWORD dlen;
-
- if (flen <= 0)
- return flen;
-
- ctx = ENGINE_get_ex_data(RSA_get0_engine(rsa), capi_idx);
-
- CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n");
-
- capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
- if (!capi_key) {
- CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY);
- return -1;
- }
-
- switch (padding) {
- case RSA_PKCS1_PADDING:
- /* Nothing to do */
- break;
-#ifdef CRYPT_DECRYPT_RSA_NO_PADDING_CHECK
- case RSA_NO_PADDING:
- flags = CRYPT_DECRYPT_RSA_NO_PADDING_CHECK;
- break;
-#endif
- default:
- {
- char errstr[10];
- BIO_snprintf(errstr, 10, "%d", padding);
- CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING);
- ERR_add_error_data(2, "padding=", errstr);
- return -1;
- }
- }
-
- /* Create temp reverse order version of input */
- if ((tmpbuf = OPENSSL_malloc(flen)) == NULL)
- return -1;
- for (i = 0; i < flen; i++)
- tmpbuf[flen - i - 1] = from[i];
-
- /* Finally decrypt it */
- dlen = flen;
- if (!CryptDecrypt(capi_key->key, 0, TRUE, flags, tmpbuf, &dlen)) {
- CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR);
- capi_addlasterror();
- OPENSSL_cleanse(tmpbuf, dlen);
- OPENSSL_free(tmpbuf);
- return -1;
- } else {
- memcpy(to, tmpbuf, (flen = (int)dlen));
- }
- OPENSSL_cleanse(tmpbuf, flen);
- OPENSSL_free(tmpbuf);
-
- return flen;
-}
-
-static int capi_rsa_free(RSA *rsa)
-{
- CAPI_KEY *capi_key;
- capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
- capi_free_key(capi_key);
- RSA_set_ex_data(rsa, rsa_capi_idx, 0);
- return 1;
-}
-
-# ifndef OPENSSL_NO_DSA
-/* CryptoAPI DSA operations */
-
-static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
- DSA *dsa)
-{
- HCRYPTHASH hash;
- DWORD slen;
- DSA_SIG *ret = NULL;
- CAPI_KEY *capi_key;
- CAPI_CTX *ctx;
- unsigned char csigbuf[40];
-
- ctx = ENGINE_get_ex_data(DSA_get0_engine(dsa), capi_idx);
-
- CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n");
-
- capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
-
- if (!capi_key) {
- CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY);
- return NULL;
- }
-
- if (dlen != 20) {
- CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH);
- return NULL;
- }
-
- /* Create the hash object */
- if (!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash)) {
- CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
- capi_addlasterror();
- return NULL;
- }
-
- /* Set the hash value to the value passed */
- if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0)) {
- CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
- capi_addlasterror();
- goto err;
- }
-
- /* Finally sign it */
- slen = sizeof(csigbuf);
- if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) {
- CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH);
- capi_addlasterror();
- goto err;
- } else {
- BIGNUM *r = BN_new(), *s = BN_new();
-
- if (r == NULL || s == NULL
- || !lend_tobn(r, csigbuf, 20)
- || !lend_tobn(s, csigbuf + 20, 20)
- || (ret = DSA_SIG_new()) == NULL) {
- BN_free(r); /* BN_free checks for BIGNUM * being NULL */
- BN_free(s);
- goto err;
- }
- DSA_SIG_set0(ret, r, s);
- }
-
- /* Now cleanup */
-
- err:
- OPENSSL_cleanse(csigbuf, 40);
- CryptDestroyHash(hash);
- return ret;
-}
-
-static int capi_dsa_free(DSA *dsa)
-{
- CAPI_KEY *capi_key;
- capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
- capi_free_key(capi_key);
- DSA_set_ex_data(dsa, dsa_capi_idx, 0);
- return 1;
-}
-# endif
-
-static void capi_vtrace(CAPI_CTX *ctx, int level, char *format,
- va_list argptr)
-{
- BIO *out;
-
- if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file))
- return;
- out = BIO_new_file(ctx->debug_file, "a+");
- if (out == NULL) {
- CAPIerr(CAPI_F_CAPI_VTRACE, CAPI_R_FILE_OPEN_ERROR);
- return;
- }
- BIO_vprintf(out, format, argptr);
- BIO_free(out);
-}
-
-static void CAPI_trace(CAPI_CTX *ctx, char *format, ...)
-{
- va_list args;
- va_start(args, format);
- capi_vtrace(ctx, CAPI_DBG_TRACE, format, args);
- va_end(args);
-}
-
-static void capi_addlasterror(void)
-{
- capi_adderror(GetLastError());
-}
-
-static void capi_adderror(DWORD err)
-{
- char errstr[10];
- BIO_snprintf(errstr, 10, "%lX", err);
- ERR_add_error_data(2, "Error code= 0x", errstr);
-}
-
-static char *wide_to_asc(LPCWSTR wstr)
-{
- char *str;
- int len_0, sz;
- size_t len_1;
-
- if (!wstr)
- return NULL;
-
- len_1 = wcslen(wstr) + 1;
-
- if (len_1 > INT_MAX) {
- CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_FUNCTION_NOT_SUPPORTED);
- return NULL;
- }
-
- len_0 = (int)len_1; /* WideCharToMultiByte expects int */
- sz = WideCharToMultiByte(CP_ACP, 0, wstr, len_0, NULL, 0, NULL, NULL);
- if (!sz) {
- CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
- return NULL;
- }
- str = OPENSSL_malloc(sz);
- if (str == NULL)
- return NULL;
- if (!WideCharToMultiByte(CP_ACP, 0, wstr, len_0, str, sz, NULL, NULL)) {
- OPENSSL_free(str);
- CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
- return NULL;
- }
- return str;
-}
-
-static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype,
- DWORD idx)
-{
- DWORD len, err;
- LPTSTR name;
- CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx);
- if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len)) {
- err = GetLastError();
- if (err == ERROR_NO_MORE_ITEMS)
- return 2;
- CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
- capi_adderror(err);
- return 0;
- }
- name = OPENSSL_malloc(len);
- if (name == NULL)
- return 0;
- if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) {
- err = GetLastError();
- OPENSSL_free(name);
- if (err == ERROR_NO_MORE_ITEMS)
- return 2;
- CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
- capi_adderror(err);
- return 0;
- }
- if (sizeof(TCHAR) != sizeof(char)) {
- *pname = wide_to_asc((WCHAR *)name);
- OPENSSL_free(name);
- if (*pname == NULL)
- return 0;
- } else {
- *pname = (char *)name;
- }
- CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", *pname,
- *ptype);
-
- return 1;
-}
-
-static int capi_list_providers(CAPI_CTX *ctx, BIO *out)
-{
- DWORD idx, ptype;
- int ret;
- LPSTR provname = NULL;
- CAPI_trace(ctx, "capi_list_providers\n");
- BIO_printf(out, "Available CSPs:\n");
- for (idx = 0;; idx++) {
- ret = capi_get_provname(ctx, &provname, &ptype, idx);
- if (ret == 2)
- break;
- if (ret == 0)
- break;
- BIO_printf(out, "%lu. %s, type %lu\n", idx, provname, ptype);
- OPENSSL_free(provname);
- }
- return 1;
-}
-
-static int capi_list_containers(CAPI_CTX *ctx, BIO *out)
-{
- int ret = 1;
- HCRYPTPROV hprov;
- DWORD err, idx, flags, buflen = 0, clen;
- LPSTR cname;
- LPWSTR cspname = NULL;
-
- CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname,
- ctx->csptype);
- if (ctx->cspname != NULL) {
- if ((clen = MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1,
- NULL, 0))) {
- cspname = alloca(clen * sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, (WCHAR *)cspname,
- clen);
- }
- if (cspname == NULL) {
- CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
- capi_addlasterror();
- return 0;
- }
- }
- if (!CryptAcquireContextW(&hprov, NULL, cspname, ctx->csptype,
- CRYPT_VERIFYCONTEXT)) {
- CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS,
- CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
- capi_addlasterror();
- return 0;
- }
- if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, NULL, &buflen,
- CRYPT_FIRST)) {
- CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
- capi_addlasterror();
- CryptReleaseContext(hprov, 0);
- return 0;
- }
- CAPI_trace(ctx, "Got max container len %d\n", buflen);
- if (buflen == 0)
- buflen = 1024;
- cname = OPENSSL_malloc(buflen);
- if (cname == NULL)
- goto err;
-
- for (idx = 0;; idx++) {
- clen = buflen;
- cname[0] = 0;
-
- if (idx == 0)
- flags = CRYPT_FIRST;
- else
- flags = 0;
- if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, (BYTE *)cname,
- &clen, flags)) {
- err = GetLastError();
- if (err == ERROR_NO_MORE_ITEMS)
- goto done;
- CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
- capi_adderror(err);
- goto err;
- }
- CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n",
- cname, clen, idx, flags);
- if (!cname[0] && (clen == buflen)) {
- CAPI_trace(ctx, "Enumerate bug: using workaround\n");
- goto done;
- }
- BIO_printf(out, "%lu. %s\n", idx, cname);
- }
- err:
-
- ret = 0;
-
- done:
- OPENSSL_free(cname);
- CryptReleaseContext(hprov, 0);
-
- return ret;
-}
-
-static CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX *ctx,
- PCCERT_CONTEXT cert)
-{
- DWORD len;
- CRYPT_KEY_PROV_INFO *pinfo;
-
- if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
- NULL, &len))
- return NULL;
- pinfo = OPENSSL_malloc(len);
- if (pinfo == NULL)
- return NULL;
- if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
- pinfo, &len)) {
- CAPIerr(CAPI_F_CAPI_GET_PROV_INFO,
- CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO);
- capi_addlasterror();
- OPENSSL_free(pinfo);
- return NULL;
- }
- return pinfo;
-}
-
-static void capi_dump_prov_info(CAPI_CTX *ctx, BIO *out,
- CRYPT_KEY_PROV_INFO *pinfo)
-{
- char *provname = NULL, *contname = NULL;
-
- if (pinfo == NULL) {
- BIO_printf(out, " No Private Key\n");
- return;
- }
- provname = wide_to_asc(pinfo->pwszProvName);
- contname = wide_to_asc(pinfo->pwszContainerName);
- if (provname == NULL || contname == NULL)
- goto err;
-
- BIO_printf(out, " Private Key Info:\n");
- BIO_printf(out, " Provider Name: %s, Provider Type %lu\n", provname,
- pinfo->dwProvType);
- BIO_printf(out, " Container Name: %s, Key Type %lu\n", contname,
- pinfo->dwKeySpec);
- err:
- OPENSSL_free(provname);
- OPENSSL_free(contname);
-}
-
-static char *capi_cert_get_fname(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
-{
- LPWSTR wfname;
- DWORD dlen;
-
- CAPI_trace(ctx, "capi_cert_get_fname\n");
- if (!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
- NULL, &dlen))
- return NULL;
- wfname = OPENSSL_malloc(dlen);
- if (wfname == NULL)
- return NULL;
- if (CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
- wfname, &dlen)) {
- char *fname = wide_to_asc(wfname);
- OPENSSL_free(wfname);
- return fname;
- }
- CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME);
- capi_addlasterror();
-
- OPENSSL_free(wfname);
- return NULL;
-}
-
-static void capi_dump_cert(CAPI_CTX *ctx, BIO *out, PCCERT_CONTEXT cert)
-{
- X509 *x;
- const unsigned char *p;
- unsigned long flags = ctx->dump_flags;
- if (flags & CAPI_DMP_FNAME) {
- char *fname;
- fname = capi_cert_get_fname(ctx, cert);
- if (fname) {
- BIO_printf(out, " Friendly Name \"%s\"\n", fname);
- OPENSSL_free(fname);
- } else {
- BIO_printf(out, " <No Friendly Name>\n");
- }
- }
-
- p = cert->pbCertEncoded;
- x = d2i_X509(NULL, &p, cert->cbCertEncoded);
- if (!x)
- BIO_printf(out, " <Can't parse certificate>\n");
- if (flags & CAPI_DMP_SUMMARY) {
- BIO_printf(out, " Subject: ");
- X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
- BIO_printf(out, "\n Issuer: ");
- X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
- BIO_printf(out, "\n");
- }
- if (flags & CAPI_DMP_FULL)
- X509_print_ex(out, x, XN_FLAG_ONELINE, 0);
-
- if (flags & CAPI_DMP_PKEYINFO) {
- CRYPT_KEY_PROV_INFO *pinfo;
- pinfo = capi_get_prov_info(ctx, cert);
- capi_dump_prov_info(ctx, out, pinfo);
- OPENSSL_free(pinfo);
- }
-
- if (flags & CAPI_DMP_PEM)
- PEM_write_bio_X509(out, x);
- X509_free(x);
-}
-
-static HCERTSTORE capi_open_store(CAPI_CTX *ctx, char *storename)
-{
- HCERTSTORE hstore;
-
- if (!storename)
- storename = ctx->storename;
- if (!storename)
- storename = "MY";
- CAPI_trace(ctx, "Opening certificate store %s\n", storename);
-
- hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
- ctx->store_flags, storename);
- if (!hstore) {
- CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE);
- capi_addlasterror();
- }
- return hstore;
-}
-
-int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *id)
-{
- char *storename;
- int idx;
- int ret = 1;
- HCERTSTORE hstore;
- PCCERT_CONTEXT cert = NULL;
-
- storename = ctx->storename;
- if (!storename)
- storename = "MY";
- CAPI_trace(ctx, "Listing certs for store %s\n", storename);
-
- hstore = capi_open_store(ctx, storename);
- if (!hstore)
- return 0;
- if (id) {
- cert = capi_find_cert(ctx, id, hstore);
- if (!cert) {
- ret = 0;
- goto err;
- }
- capi_dump_cert(ctx, out, cert);
- CertFreeCertificateContext(cert);
- } else {
- for (idx = 0;; idx++) {
- cert = CertEnumCertificatesInStore(hstore, cert);
- if (!cert)
- break;
- BIO_printf(out, "Certificate %d\n", idx);
- capi_dump_cert(ctx, out, cert);
- }
- }
- err:
- CertCloseStore(hstore, 0);
- return ret;
-}
-
-static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id,
- HCERTSTORE hstore)
-{
- PCCERT_CONTEXT cert = NULL;
- char *fname = NULL;
- int match;
- switch (ctx->lookup_method) {
- case CAPI_LU_SUBSTR:
- return CertFindCertificateInStore(hstore, X509_ASN_ENCODING, 0,
- CERT_FIND_SUBJECT_STR_A, id, NULL);
- case CAPI_LU_FNAME:
- for (;;) {
- cert = CertEnumCertificatesInStore(hstore, cert);
- if (!cert)
- return NULL;
- fname = capi_cert_get_fname(ctx, cert);
- if (fname) {
- if (strcmp(fname, id))
- match = 0;
- else
- match = 1;
- OPENSSL_free(fname);
- if (match)
- return cert;
- }
- }
- default:
- return NULL;
- }
-}
-
-static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const WCHAR *contname,
- const WCHAR *provname, DWORD ptype,
- DWORD keyspec)
-{
- DWORD dwFlags = 0;
- CAPI_KEY *key = OPENSSL_malloc(sizeof(*key));
-
- if (key == NULL)
- return NULL;
- /* If PROV_RSA_AES supported use it instead */
- if (ptype == PROV_RSA_FULL && use_aes_csp &&
- wcscmp(provname, rsa_enh_cspname) == 0) {
- provname = rsa_aes_cspname;
- ptype = PROV_RSA_AES;
- }
- if (ctx && ctx->debug_level >= CAPI_DBG_TRACE && ctx->debug_file) {
- /*
- * above 'if' is [complementary] copy from CAPI_trace and serves
- * as optimization to minimize [below] malloc-ations
- */
- char *_contname = wide_to_asc(contname);
- char *_provname = wide_to_asc(provname);
-
- CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
- _contname, _provname, ptype);
- OPENSSL_free(_provname);
- OPENSSL_free(_contname);
- }
- if (ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE)
- dwFlags = CRYPT_MACHINE_KEYSET;
- if (!CryptAcquireContextW(&key->hprov, contname, provname, ptype,
- dwFlags)) {
- CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
- capi_addlasterror();
- goto err;
- }
- if (!CryptGetUserKey(key->hprov, keyspec, &key->key)) {
- CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR);
- capi_addlasterror();
- CryptReleaseContext(key->hprov, 0);
- goto err;
- }
- key->keyspec = keyspec;
- key->pcert = NULL;
- return key;
-
- err:
- OPENSSL_free(key);
- return NULL;
-}
-
-static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
-{
- CAPI_KEY *key = NULL;
- CRYPT_KEY_PROV_INFO *pinfo = NULL;
-
- pinfo = capi_get_prov_info(ctx, cert);
-
- if (pinfo != NULL)
- key = capi_get_key(ctx, pinfo->pwszContainerName, pinfo->pwszProvName,
- pinfo->dwProvType, pinfo->dwKeySpec);
-
- OPENSSL_free(pinfo);
- return key;
-}
-
-CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id)
-{
- PCCERT_CONTEXT cert;
- HCERTSTORE hstore;
- CAPI_KEY *key = NULL;
-
- switch (ctx->lookup_method) {
- case CAPI_LU_SUBSTR:
- case CAPI_LU_FNAME:
- hstore = capi_open_store(ctx, NULL);
- if (!hstore)
- return NULL;
- cert = capi_find_cert(ctx, id, hstore);
- if (cert) {
- key = capi_get_cert_key(ctx, cert);
- CertFreeCertificateContext(cert);
- }
- CertCloseStore(hstore, 0);
- break;
-
- case CAPI_LU_CONTNAME:
- {
- WCHAR *contname, *provname;
- DWORD len;
-
- if ((len = MultiByteToWideChar(CP_ACP, 0, id, -1, NULL, 0)) &&
- (contname = alloca(len * sizeof(WCHAR)),
- MultiByteToWideChar(CP_ACP, 0, id, -1, contname, len)) &&
- (len = MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1,
- NULL, 0)) &&
- (provname = alloca(len * sizeof(WCHAR)),
- MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1,
- provname, len)))
- key = capi_get_key(ctx, contname, provname,
- ctx->csptype, ctx->keytype);
- }
- break;
- }
-
- return key;
-}
-
-void capi_free_key(CAPI_KEY *key)
-{
- if (!key)
- return;
- CryptDestroyKey(key->key);
- CryptReleaseContext(key->hprov, 0);
- if (key->pcert)
- CertFreeCertificateContext(key->pcert);
- OPENSSL_free(key);
-}
-
-/* Initialize a CAPI_CTX structure */
-
-static CAPI_CTX *capi_ctx_new(void)
-{
- CAPI_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
-
- if (ctx == NULL)
- return NULL;
- ctx->csptype = PROV_RSA_FULL;
- ctx->dump_flags = CAPI_DMP_SUMMARY | CAPI_DMP_FNAME;
- ctx->keytype = AT_KEYEXCHANGE;
- ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG |
- CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER;
- ctx->lookup_method = CAPI_LU_SUBSTR;
- ctx->client_cert_select = cert_select_simple;
- return ctx;
-}
-
-static void capi_ctx_free(CAPI_CTX *ctx)
-{
- CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx);
- if (!ctx)
- return;
- OPENSSL_free(ctx->cspname);
- OPENSSL_free(ctx->debug_file);
- OPENSSL_free(ctx->storename);
- OPENSSL_free(ctx->ssl_client_store);
- OPENSSL_free(ctx);
-}
-
-static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type,
- int check)
-{
- LPSTR tmpcspname;
-
- CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type);
- if (check) {
- HCRYPTPROV hprov;
- LPWSTR name = NULL;
- DWORD len;
-
- if ((len = MultiByteToWideChar(CP_ACP, 0, pname, -1, NULL, 0))) {
- name = alloca(len * sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, pname, -1, (WCHAR *)name, len);
- }
- if (name == NULL || !CryptAcquireContextW(&hprov, NULL, name, type,
- CRYPT_VERIFYCONTEXT)) {
- CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME,
- CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
- capi_addlasterror();
- return 0;
- }
- CryptReleaseContext(hprov, 0);
- }
- tmpcspname = OPENSSL_strdup(pname);
- if (tmpcspname == NULL)
- return 0;
- OPENSSL_free(ctx->cspname);
- ctx->cspname = tmpcspname;
- ctx->csptype = type;
- return 1;
-}
-
-static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx)
-{
- LPSTR pname;
- DWORD type;
- int res;
- if (capi_get_provname(ctx, &pname, &type, idx) != 1)
- return 0;
- res = capi_ctx_set_provname(ctx, pname, type, 0);
- OPENSSL_free(pname);
- return res;
-}
-
-static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x)
-{
- int i;
- X509_NAME *nm;
- /* Special case: empty list: match anything */
- if (sk_X509_NAME_num(ca_dn) <= 0)
- return 1;
- for (i = 0; i < sk_X509_NAME_num(ca_dn); i++) {
- nm = sk_X509_NAME_value(ca_dn, i);
- if (!X509_NAME_cmp(nm, X509_get_issuer_name(x)))
- return 1;
- }
- return 0;
-}
-
-static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
- STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
- EVP_PKEY **pkey, STACK_OF(X509) **pother,
- UI_METHOD *ui_method,
- void *callback_data)
-{
- STACK_OF(X509) *certs = NULL;
- X509 *x;
- char *storename;
- const unsigned char *p;
- int i, client_cert_idx;
- HCERTSTORE hstore;
- PCCERT_CONTEXT cert = NULL, excert = NULL;
- CAPI_CTX *ctx;
- CAPI_KEY *key;
- ctx = ENGINE_get_ex_data(e, capi_idx);
-
- *pcert = NULL;
- *pkey = NULL;
-
- storename = ctx->ssl_client_store;
- if (!storename)
- storename = "MY";
-
- hstore = capi_open_store(ctx, storename);
- if (!hstore)
- return 0;
- /* Enumerate all certificates collect any matches */
- for (i = 0;; i++) {
- cert = CertEnumCertificatesInStore(hstore, cert);
- if (!cert)
- break;
- p = cert->pbCertEncoded;
- x = d2i_X509(NULL, &p, cert->cbCertEncoded);
- if (!x) {
- CAPI_trace(ctx, "Can't Parse Certificate %d\n", i);
- continue;
- }
- if (cert_issuer_match(ca_dn, x)
- && X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0)) {
- key = capi_get_cert_key(ctx, cert);
- if (!key) {
- X509_free(x);
- continue;
- }
- /*
- * Match found: attach extra data to it so we can retrieve the
- * key later.
- */
- excert = CertDuplicateCertificateContext(cert);
- key->pcert = excert;
- X509_set_ex_data(x, cert_capi_idx, key);
-
- if (!certs)
- certs = sk_X509_new_null();
-
- if (!sk_X509_push(certs, x)) {
- X509_free(x);
- continue;
- }
- } else {
- X509_free(x);
- }
- }
-
- if (cert)
- CertFreeCertificateContext(cert);
- if (hstore)
- CertCloseStore(hstore, 0);
-
- if (!certs)
- return 0;
-
- /* Select the appropriate certificate */
-
- client_cert_idx = ctx->client_cert_select(e, ssl, certs);
-
- /* Set the selected certificate and free the rest */
-
- for (i = 0; i < sk_X509_num(certs); i++) {
- x = sk_X509_value(certs, i);
- if (i == client_cert_idx)
- *pcert = x;
- else {
- key = X509_get_ex_data(x, cert_capi_idx);
- capi_free_key(key);
- X509_free(x);
- }
- }
-
- sk_X509_free(certs);
-
- if (*pcert == NULL)
- return 0;
-
- /* Setup key for selected certificate */
-
- key = X509_get_ex_data(*pcert, cert_capi_idx);
- *pkey = capi_get_pkey(e, key);
- X509_set_ex_data(*pcert, cert_capi_idx, NULL);
-
- return 1;
-
-}
-
-/* Simple client cert selection function: always select first */
-
-static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
-{
- return 0;
-}
-
-# ifdef OPENSSL_CAPIENG_DIALOG
-
-/*
- * More complex cert selection function, using standard function
- * CryptUIDlgSelectCertificateFromStore() to produce a dialog box.
- */
-
-/*
- * Definitions which are in cryptuiapi.h but this is not present in older
- * versions of headers.
- */
-
-# ifndef CRYPTUI_SELECT_LOCATION_COLUMN
-# define CRYPTUI_SELECT_LOCATION_COLUMN 0x000000010
-# define CRYPTUI_SELECT_INTENDEDUSE_COLUMN 0x000000004
-# endif
-
-# define dlg_title L"OpenSSL Application SSL Client Certificate Selection"
-# define dlg_prompt L"Select a certificate to use for authentication"
-# define dlg_columns CRYPTUI_SELECT_LOCATION_COLUMN \
- |CRYPTUI_SELECT_INTENDEDUSE_COLUMN
-
-static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
-{
- X509 *x;
- HCERTSTORE dstore;
- PCCERT_CONTEXT cert;
- CAPI_CTX *ctx;
- CAPI_KEY *key;
- HWND hwnd;
- int i, idx = -1;
- if (sk_X509_num(certs) == 1)
- return 0;
- ctx = ENGINE_get_ex_data(e, capi_idx);
- /* Create an in memory store of certificates */
- dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
- CERT_STORE_CREATE_NEW_FLAG, NULL);
- if (!dstore) {
- CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE);
- capi_addlasterror();
- goto err;
- }
- /* Add all certificates to store */
- for (i = 0; i < sk_X509_num(certs); i++) {
- x = sk_X509_value(certs, i);
- key = X509_get_ex_data(x, cert_capi_idx);
-
- if (!CertAddCertificateContextToStore(dstore, key->pcert,
- CERT_STORE_ADD_NEW, NULL)) {
- CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT);
- capi_addlasterror();
- goto err;
- }
-
- }
- hwnd = GetForegroundWindow();
- if (!hwnd)
- hwnd = GetActiveWindow();
- if (!hwnd && ctx->getconswindow)
- hwnd = ctx->getconswindow();
- /* Call dialog to select one */
- cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt,
- dlg_columns, 0, NULL);
-
- /* Find matching cert from list */
- if (cert) {
- for (i = 0; i < sk_X509_num(certs); i++) {
- x = sk_X509_value(certs, i);
- key = X509_get_ex_data(x, cert_capi_idx);
- if (CertCompareCertificate
- (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert->pCertInfo,
- key->pcert->pCertInfo)) {
- idx = i;
- break;
- }
- }
- }
-
- err:
- if (dstore)
- CertCloseStore(dstore, 0);
- return idx;
-
-}
-# endif
-
-#else /* !__COMPILE_CAPIENG */
-# include <openssl/engine.h>
-void engine_load_capi_int(void);
-void engine_load_capi_int(void)
-{
-}
-#endif
+++ /dev/null
-# The INPUT HEADER is scanned for declarations
-# LIBNAME INPUT HEADER ERROR-TABLE FILE
-L CAPI e_capi_err.h e_capi_err.c
+++ /dev/null
-# 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
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-# The INPUT HEADER is scanned for declarations
-# LIBNAME INPUT HEADER ERROR-TABLE FILE
-L DASYNC e_dasync_err.h e_dasync_err.c
+++ /dev/null
-# 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
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * Copyright 2017-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
- */
-
-/* We need to use some deprecated APIs */
-#define OPENSSL_SUPPRESS_DEPRECATED
-
-#include "internal/e_os.h"
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include <openssl/conf.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include <openssl/engine.h>
-#include <openssl/objects.h>
-#include "crypto/cryptodev.h"
-#include "internal/nelem.h"
-
-/* #define ENGINE_DEVCRYPTO_DEBUG */
-
-#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
-# define CHECK_BSD_STYLE_MACROS
-#endif
-
-#define engine_devcrypto_id "devcrypto"
-
-/*
- * Use session2_op on FreeBSD which permits requesting specific
- * drivers or classes of drivers at session creation time.
- */
-#ifdef CIOCGSESSION2
-typedef struct session2_op session_op_t;
-#else
-typedef struct session_op session_op_t;
-#endif
-
-/*
- * ONE global file descriptor for all sessions. This allows operations
- * such as digest session data copying (see digest_copy()), but is also
- * saner... why re-open /dev/crypto for every session?
- */
-static int cfd = -1;
-#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
-#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */
-#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */
-
-#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE
-static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS;
-
-/*
- * cipher/digest status & acceleration definitions
- * Make sure the defaults are set to 0
- */
-struct driver_info_st {
- enum devcrypto_status_t {
- DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */
- DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */
- DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
- DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
- DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
- } status;
-
- enum devcrypto_accelerated_t {
- DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
- DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unknown */
- DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
- } accelerated;
-
- char *driver_name;
-};
-
-void engine_load_devcrypto_int(void);
-
-static int clean_devcrypto_session(session_op_t *sess) {
- if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
- ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
- return 0;
- }
- memset(sess, 0, sizeof(*sess));
- return 1;
-}
-
-/******************************************************************************
- *
- * Ciphers
- *
- * Because they all do the same basic operation, we have only one set of
- * method functions for them all to share, and a mapping table between
- * NIDs and cryptodev IDs, with all the necessary size data.
- *
- *****/
-
-struct cipher_ctx {
- session_op_t sess;
- int op; /* COP_ENCRYPT or COP_DECRYPT */
- unsigned long mode; /* EVP_CIPH_*_MODE */
-
- /* to handle ctr mode being a stream cipher */
- unsigned char partial[EVP_MAX_BLOCK_LENGTH];
- unsigned int blocksize, num;
-};
-
-static const struct cipher_data_st {
- int nid;
- int blocksize;
- int keylen;
- int ivlen;
- int flags;
- int devcryptoid;
-} cipher_data[] = {
-#ifndef OPENSSL_NO_DES
- { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
- { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
-#endif
-#ifndef OPENSSL_NO_BF
- { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
-#endif
-#ifndef OPENSSL_NO_CAST
- { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
-#endif
- { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
- { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
- { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
-#ifndef OPENSSL_NO_RC4
- { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
- { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
- { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
- { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
-#endif
-#if 0 /* Not yet supported */
- { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
- { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
- { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
- { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
- { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
-#endif
-#if 0 /* Not yet supported */
- { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
- { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
- { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
-#endif
-#ifndef OPENSSL_NO_CAMELLIA
- { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
- CRYPTO_CAMELLIA_CBC },
- { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
- CRYPTO_CAMELLIA_CBC },
- { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
- CRYPTO_CAMELLIA_CBC },
-#endif
-};
-
-static size_t find_cipher_data_index(int nid)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(cipher_data); i++)
- if (nid == cipher_data[i].nid)
- return i;
- return (size_t)-1;
-}
-
-static size_t get_cipher_data_index(int nid)
-{
- size_t i = find_cipher_data_index(nid);
-
- if (i != (size_t)-1)
- return i;
-
- /*
- * Code further down must make sure that only NIDs in the table above
- * are used. If any other NID reaches this function, there's a grave
- * coding error further down.
- */
- assert("Code that never should be reached" == NULL);
- return -1;
-}
-
-static const struct cipher_data_st *get_cipher_data(int nid)
-{
- return &cipher_data[get_cipher_data_index(nid)];
-}
-
-/*
- * Following are the three necessary functions to map OpenSSL functionality
- * with cryptodev.
- */
-
-static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- const struct cipher_data_st *cipher_d =
- get_cipher_data(EVP_CIPHER_CTX_get_nid(ctx));
- int ret;
-
- /* cleanup a previous session */
- if (cipher_ctx->sess.ses != 0 &&
- clean_devcrypto_session(&cipher_ctx->sess) == 0)
- return 0;
-
- cipher_ctx->sess.cipher = cipher_d->devcryptoid;
- cipher_ctx->sess.keylen = cipher_d->keylen;
- cipher_ctx->sess.key = (void *)key;
- cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
- cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
- cipher_ctx->blocksize = cipher_d->blocksize;
-#ifdef CIOCGSESSION2
- cipher_ctx->sess.crid = (use_softdrivers == DEVCRYPTO_USE_SOFTWARE) ?
- CRYPTO_FLAG_SOFTWARE | CRYPTO_FLAG_HARDWARE :
- CRYPTO_FLAG_HARDWARE;
- ret = ioctl(cfd, CIOCGSESSION2, &cipher_ctx->sess);
-#else
- ret = ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess);
-#endif
- if (ret < 0) {
- ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
- return 0;
- }
-
- return 1;
-}
-
-static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- struct crypt_op cryp;
- unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
-#if !defined(COP_FLAG_WRITE_IV)
- unsigned char saved_iv[EVP_MAX_IV_LENGTH];
- const unsigned char *ivptr;
- size_t nblocks, ivlen;
-#endif
-
- memset(&cryp, 0, sizeof(cryp));
- cryp.ses = cipher_ctx->sess.ses;
- cryp.len = inl;
- cryp.src = (void *)in;
- cryp.dst = (void *)out;
- cryp.iv = (void *)iv;
- cryp.op = cipher_ctx->op;
-#if !defined(COP_FLAG_WRITE_IV)
- cryp.flags = 0;
-
- ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
- if (ivlen > 0)
- switch (cipher_ctx->mode) {
- case EVP_CIPH_CBC_MODE:
- assert(inl >= ivlen);
- if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
- ivptr = in + inl - ivlen;
- memcpy(saved_iv, ivptr, ivlen);
- }
- break;
-
- case EVP_CIPH_CTR_MODE:
- break;
-
- default: /* should not happen */
- return 0;
- }
-#else
- cryp.flags = COP_FLAG_WRITE_IV;
-#endif
-
- if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
- ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
- return 0;
- }
-
-#if !defined(COP_FLAG_WRITE_IV)
- if (ivlen > 0)
- switch (cipher_ctx->mode) {
- case EVP_CIPH_CBC_MODE:
- assert(inl >= ivlen);
- if (EVP_CIPHER_CTX_is_encrypting(ctx))
- ivptr = out + inl - ivlen;
- else
- ivptr = saved_iv;
-
- memcpy(iv, ivptr, ivlen);
- break;
-
- case EVP_CIPH_CTR_MODE:
- nblocks = (inl + cipher_ctx->blocksize - 1)
- / cipher_ctx->blocksize;
- do {
- ivlen--;
- nblocks += iv[ivlen];
- iv[ivlen] = (uint8_t) nblocks;
- nblocks >>= 8;
- } while (ivlen);
- break;
-
- default: /* should not happen */
- return 0;
- }
-#endif
-
- return 1;
-}
-
-static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- size_t nblocks, len;
-
- /* initial partial block */
- while (cipher_ctx->num && inl) {
- (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
- --inl;
- cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
- }
-
- /* full blocks */
- if (inl > cipher_ctx->blocksize) {
- nblocks = inl/cipher_ctx->blocksize;
- len = nblocks * cipher_ctx->blocksize;
- if (cipher_do_cipher(ctx, out, in, len) < 1)
- return 0;
- inl -= len;
- out += len;
- in += len;
- }
-
- /* final partial block */
- if (inl) {
- memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
- if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
- cipher_ctx->blocksize) < 1)
- return 0;
- while (inl--) {
- out[cipher_ctx->num] = in[cipher_ctx->num]
- ^ cipher_ctx->partial[cipher_ctx->num];
- cipher_ctx->num++;
- }
- }
-
- return 1;
-}
-
-static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
- struct cipher_ctx *to_cipher_ctx;
-
- switch (type) {
-
- case EVP_CTRL_COPY:
- if (cipher_ctx == NULL)
- return 1;
- /* when copying the context, a new session needs to be initialized */
- to_cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
- memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
- return cipher_init(to_ctx, (void *)cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
- (cipher_ctx->op == COP_ENCRYPT));
-
- case EVP_CTRL_INIT:
- memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
- return 1;
-
- default:
- break;
- }
-
- return -1;
-}
-
-static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
-
- return clean_devcrypto_session(&cipher_ctx->sess);
-}
-
-/*
- * Keep tables of known nids, associated methods, selected ciphers, and driver
- * info.
- * Note that known_cipher_nids[] isn't necessarily indexed the same way as
- * cipher_data[] above, which the other tables are.
- */
-static int known_cipher_nids[OSSL_NELEM(cipher_data)];
-static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
-static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
-static int selected_ciphers[OSSL_NELEM(cipher_data)];
-static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
-
-
-static int devcrypto_test_cipher(size_t cipher_data_index)
-{
- return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
- && selected_ciphers[cipher_data_index] == 1
- && (cipher_driver_info[cipher_data_index].accelerated
- == DEVCRYPTO_ACCELERATED
- || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
- || (cipher_driver_info[cipher_data_index].accelerated
- != DEVCRYPTO_NOT_ACCELERATED
- && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
-}
-
-static void prepare_cipher_methods(void)
-{
- size_t i;
- session_op_t sess;
- unsigned long cipher_mode;
-#ifdef CIOCGSESSION2
- struct crypt_find_op fop;
- enum devcrypto_accelerated_t accelerated;
-#elif defined(CIOCGSESSINFO)
- struct session_info_op siop;
-#endif
-
- memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
-
- memset(&sess, 0, sizeof(sess));
- sess.key = (void *)"01234567890123456789012345678901234567890123456789";
-
- for (i = 0, known_cipher_nids_amount = 0;
- i < OSSL_NELEM(cipher_data); i++) {
-
- selected_ciphers[i] = 1;
- /*
- * Check that the cipher is usable
- */
- sess.cipher = cipher_data[i].devcryptoid;
- sess.keylen = cipher_data[i].keylen;
-#ifdef CIOCGSESSION2
- /*
- * When using CIOCGSESSION2, first try to allocate a hardware
- * ("accelerated") session. If that fails, fall back to
- * allocating a software session.
- */
- sess.crid = CRYPTO_FLAG_HARDWARE;
- if (ioctl(cfd, CIOCGSESSION2, &sess) == 0) {
- accelerated = DEVCRYPTO_ACCELERATED;
- } else {
- sess.crid = CRYPTO_FLAG_SOFTWARE;
- if (ioctl(cfd, CIOCGSESSION2, &sess) < 0) {
- cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
- continue;
- }
- accelerated = DEVCRYPTO_NOT_ACCELERATED;
- }
-#else
- if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
- cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
- continue;
- }
-#endif
-
- cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
-
- if ((known_cipher_methods[i] =
- EVP_CIPHER_meth_new(cipher_data[i].nid,
- cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
- cipher_data[i].blocksize,
- cipher_data[i].keylen)) == NULL
- || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
- cipher_data[i].ivlen)
- || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
- cipher_data[i].flags
- | EVP_CIPH_CUSTOM_COPY
- | EVP_CIPH_CTRL_INIT
- | EVP_CIPH_FLAG_DEFAULT_ASN1)
- || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
- || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
- cipher_mode == EVP_CIPH_CTR_MODE ?
- ctr_do_cipher :
- cipher_do_cipher)
- || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
- || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
- cipher_cleanup)
- || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
- sizeof(struct cipher_ctx))) {
- cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
- EVP_CIPHER_meth_free(known_cipher_methods[i]);
- known_cipher_methods[i] = NULL;
- } else {
- cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
-#ifdef CIOCGSESSION2
- cipher_driver_info[i].accelerated = accelerated;
- fop.crid = sess.crid;
- if (ioctl(cfd, CIOCFINDDEV, &fop) == 0) {
- cipher_driver_info[i].driver_name =
- OPENSSL_strndup(fop.name, sizeof(fop.name));
- }
-#elif defined(CIOCGSESSINFO)
- siop.ses = sess.ses;
- if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
- cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
- } else {
- cipher_driver_info[i].driver_name =
- OPENSSL_strndup(siop.cipher_info.cra_driver_name,
- CRYPTODEV_MAX_ALG_NAME);
- if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
- cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
- else
- cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
- }
-#endif /* CIOCGSESSINFO */
- }
- ioctl(cfd, CIOCFSESSION, &sess.ses);
- if (devcrypto_test_cipher(i)) {
- known_cipher_nids[known_cipher_nids_amount++] =
- cipher_data[i].nid;
- }
- }
-}
-
-static void rebuild_known_cipher_nids(ENGINE *e)
-{
- size_t i;
-
- for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
- if (devcrypto_test_cipher(i))
- known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
- }
- ENGINE_unregister_ciphers(e);
- ENGINE_register_ciphers(e);
-}
-
-static const EVP_CIPHER *get_cipher_method(int nid)
-{
- size_t i = get_cipher_data_index(nid);
-
- if (i == (size_t)-1)
- return NULL;
- return known_cipher_methods[i];
-}
-
-static int get_cipher_nids(const int **nids)
-{
- *nids = known_cipher_nids;
- return known_cipher_nids_amount;
-}
-
-static void destroy_cipher_method(int nid)
-{
- size_t i = get_cipher_data_index(nid);
-
- EVP_CIPHER_meth_free(known_cipher_methods[i]);
- known_cipher_methods[i] = NULL;
-}
-
-static void destroy_all_cipher_methods(void)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
- destroy_cipher_method(cipher_data[i].nid);
- OPENSSL_free(cipher_driver_info[i].driver_name);
- cipher_driver_info[i].driver_name = NULL;
- }
-}
-
-static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
- const int **nids, int nid)
-{
- if (cipher == NULL)
- return get_cipher_nids(nids);
-
- *cipher = get_cipher_method(nid);
-
- return *cipher != NULL;
-}
-
-static void devcrypto_select_all_ciphers(int *cipher_list)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(cipher_data); i++)
- cipher_list[i] = 1;
-}
-
-static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
-{
- int *cipher_list = (int *)usr;
- char *name;
- const EVP_CIPHER *EVP;
- size_t i;
-
- if (len == 0)
- return 1;
- if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
- return 0;
- EVP = EVP_get_cipherbyname(name);
- if (EVP == NULL)
- fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
- else if ((i = find_cipher_data_index(EVP_CIPHER_get_nid(EVP))) != (size_t)-1)
- cipher_list[i] = 1;
- else
- fprintf(stderr, "devcrypto: cipher %s not available\n", name);
- OPENSSL_free(name);
- return 1;
-}
-
-static void dump_cipher_info(void)
-{
- size_t i;
- const char *name;
-
- fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
- " engine:\n");
-#ifndef CIOCGSESSINFO
- fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
-#endif
- for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
- name = OBJ_nid2sn(cipher_data[i].nid);
- fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
- name ? name : "unknown", cipher_data[i].nid,
- cipher_data[i].devcryptoid);
- if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
- fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
- continue;
- }
- fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
- cipher_driver_info[i].driver_name : "unknown");
- if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
- fprintf(stderr, "(hw accelerated)");
- else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
- fprintf(stderr, "(software)");
- else
- fprintf(stderr, "(acceleration status unknown)");
- if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
- fprintf (stderr, ". Cipher setup failed");
- fprintf(stderr, "\n");
- }
- fprintf(stderr, "\n");
-}
-
-/*
- * We only support digests if the cryptodev implementation supports multiple
- * data updates and session copying. Otherwise, we would be forced to maintain
- * a cache, which is perilous if there's a lot of data coming in (if someone
- * wants to checksum an OpenSSL tarball, for example).
- */
-#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
-#define IMPLEMENT_DIGEST
-
-/******************************************************************************
- *
- * Digests
- *
- * Because they all do the same basic operation, we have only one set of
- * method functions for them all to share, and a mapping table between
- * NIDs and cryptodev IDs, with all the necessary size data.
- *
- *****/
-
-struct digest_ctx {
- session_op_t sess;
- /* This signals that the init function was called, not that it succeeded. */
- int init_called;
- unsigned char digest_res[HASH_MAX_LEN];
-};
-
-static const struct digest_data_st {
- int nid;
- int blocksize;
- int digestlen;
- int devcryptoid;
-} digest_data[] = {
-#ifndef OPENSSL_NO_MD5
- { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
-#endif
- { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
-#ifndef OPENSSL_NO_RMD160
-# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
- { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
-# endif
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
- { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
- { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
- { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
- { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
-#endif
-};
-
-static size_t find_digest_data_index(int nid)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(digest_data); i++)
- if (nid == digest_data[i].nid)
- return i;
- return (size_t)-1;
-}
-
-static size_t get_digest_data_index(int nid)
-{
- size_t i = find_digest_data_index(nid);
-
- if (i != (size_t)-1)
- return i;
-
- /*
- * Code further down must make sure that only NIDs in the table above
- * are used. If any other NID reaches this function, there's a grave
- * coding error further down.
- */
- assert("Code that never should be reached" == NULL);
- return -1;
-}
-
-static const struct digest_data_st *get_digest_data(int nid)
-{
- return &digest_data[get_digest_data_index(nid)];
-}
-
-/*
- * Following are the five necessary functions to map OpenSSL functionality
- * with cryptodev: init, update, final, cleanup, and copy.
- */
-
-static int digest_init(EVP_MD_CTX *ctx)
-{
- struct digest_ctx *digest_ctx =
- (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
- const struct digest_data_st *digest_d =
- get_digest_data(EVP_MD_CTX_get_type(ctx));
-
- digest_ctx->init_called = 1;
-
- memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
- digest_ctx->sess.mac = digest_d->devcryptoid;
- if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
- ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
- return 0;
- }
- return 1;
-}
-
-static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
- void *res, unsigned int flags)
-{
- struct crypt_op cryp;
-
- memset(&cryp, 0, sizeof(cryp));
- cryp.ses = ctx->sess.ses;
- cryp.len = srclen;
- cryp.src = (void *)src;
- cryp.dst = NULL;
- cryp.mac = res;
- cryp.flags = flags;
- return ioctl(cfd, CIOCCRYPT, &cryp);
-}
-
-static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- struct digest_ctx *digest_ctx =
- (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
-
- if (count == 0)
- return 1;
-
- if (digest_ctx == NULL)
- return 0;
-
- if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
- if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
- return 1;
- } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
- return 1;
- }
-
- ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
- return 0;
-}
-
-static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- struct digest_ctx *digest_ctx =
- (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
-
- if (md == NULL || digest_ctx == NULL)
- return 0;
-
- if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
- memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_get_size(ctx));
- } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
- ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
- return 0;
- }
-
- return 1;
-}
-
-static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
-{
- struct digest_ctx *digest_from =
- (struct digest_ctx *)EVP_MD_CTX_get0_md_data(from);
- struct digest_ctx *digest_to =
- (struct digest_ctx *)EVP_MD_CTX_get0_md_data(to);
- struct cphash_op cphash;
-
- if (digest_from == NULL || digest_from->init_called != 1)
- return 1;
-
- if (!digest_init(to)) {
- ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
- return 0;
- }
-
- cphash.src_ses = digest_from->sess.ses;
- cphash.dst_ses = digest_to->sess.ses;
- if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
- ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
- return 0;
- }
- return 1;
-}
-
-static int digest_cleanup(EVP_MD_CTX *ctx)
-{
- struct digest_ctx *digest_ctx =
- (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
-
- if (digest_ctx == NULL)
- return 1;
-
- return clean_devcrypto_session(&digest_ctx->sess);
-}
-
-/*
- * Keep tables of known nids, associated methods, selected digests, and
- * driver info.
- * Note that known_digest_nids[] isn't necessarily indexed the same way as
- * digest_data[] above, which the other tables are.
- */
-static int known_digest_nids[OSSL_NELEM(digest_data)];
-static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
-static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
-static int selected_digests[OSSL_NELEM(digest_data)];
-static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
-
-static int devcrypto_test_digest(size_t digest_data_index)
-{
- return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
- && selected_digests[digest_data_index] == 1
- && (digest_driver_info[digest_data_index].accelerated
- == DEVCRYPTO_ACCELERATED
- || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
- || (digest_driver_info[digest_data_index].accelerated
- != DEVCRYPTO_NOT_ACCELERATED
- && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
-}
-
-static void rebuild_known_digest_nids(ENGINE *e)
-{
- size_t i;
-
- for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
- if (devcrypto_test_digest(i))
- known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
- }
- ENGINE_unregister_digests(e);
- ENGINE_register_digests(e);
-}
-
-static void prepare_digest_methods(void)
-{
- size_t i;
- session_op_t sess1, sess2;
-#ifdef CIOCGSESSINFO
- struct session_info_op siop;
-#endif
- struct cphash_op cphash;
-
- memset(&digest_driver_info, 0, sizeof(digest_driver_info));
-
- memset(&sess1, 0, sizeof(sess1));
- memset(&sess2, 0, sizeof(sess2));
-
- for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
- i++) {
-
- selected_digests[i] = 1;
-
- /*
- * Check that the digest is usable
- */
- sess1.mac = digest_data[i].devcryptoid;
- sess2.ses = 0;
- if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
- digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
- goto finish;
- }
-
-#ifdef CIOCGSESSINFO
- /* gather hardware acceleration info from the driver */
- siop.ses = sess1.ses;
- if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
- digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
- } else {
- digest_driver_info[i].driver_name =
- OPENSSL_strndup(siop.hash_info.cra_driver_name,
- CRYPTODEV_MAX_ALG_NAME);
- if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
- digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
- else
- digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
- }
-#endif
-
- /* digest must be capable of hash state copy */
- sess2.mac = sess1.mac;
- if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
- digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
- goto finish;
- }
- cphash.src_ses = sess1.ses;
- cphash.dst_ses = sess2.ses;
- if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
- digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
- goto finish;
- }
- if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
- NID_undef)) == NULL
- || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
- digest_data[i].blocksize)
- || !EVP_MD_meth_set_result_size(known_digest_methods[i],
- digest_data[i].digestlen)
- || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
- || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
- || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
- || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
- || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
- || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
- sizeof(struct digest_ctx))) {
- digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
- EVP_MD_meth_free(known_digest_methods[i]);
- known_digest_methods[i] = NULL;
- goto finish;
- }
- digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
-finish:
- ioctl(cfd, CIOCFSESSION, &sess1.ses);
- if (sess2.ses != 0)
- ioctl(cfd, CIOCFSESSION, &sess2.ses);
- if (devcrypto_test_digest(i))
- known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
- }
-}
-
-static const EVP_MD *get_digest_method(int nid)
-{
- size_t i = get_digest_data_index(nid);
-
- if (i == (size_t)-1)
- return NULL;
- return known_digest_methods[i];
-}
-
-static int get_digest_nids(const int **nids)
-{
- *nids = known_digest_nids;
- return known_digest_nids_amount;
-}
-
-static void destroy_digest_method(int nid)
-{
- size_t i = get_digest_data_index(nid);
-
- EVP_MD_meth_free(known_digest_methods[i]);
- known_digest_methods[i] = NULL;
-}
-
-static void destroy_all_digest_methods(void)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(digest_data); i++) {
- destroy_digest_method(digest_data[i].nid);
- OPENSSL_free(digest_driver_info[i].driver_name);
- digest_driver_info[i].driver_name = NULL;
- }
-}
-
-static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
- const int **nids, int nid)
-{
- if (digest == NULL)
- return get_digest_nids(nids);
-
- *digest = get_digest_method(nid);
-
- return *digest != NULL;
-}
-
-static void devcrypto_select_all_digests(int *digest_list)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(digest_data); i++)
- digest_list[i] = 1;
-}
-
-static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
-{
- int *digest_list = (int *)usr;
- char *name;
- const EVP_MD *EVP;
- size_t i;
-
- if (len == 0)
- return 1;
- if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
- return 0;
- EVP = EVP_get_digestbyname(name);
- if (EVP == NULL)
- fprintf(stderr, "devcrypto: unknown digest %s\n", name);
- else if ((i = find_digest_data_index(EVP_MD_get_type(EVP))) != (size_t)-1)
- digest_list[i] = 1;
- else
- fprintf(stderr, "devcrypto: digest %s not available\n", name);
- OPENSSL_free(name);
- return 1;
-}
-
-static void dump_digest_info(void)
-{
- size_t i;
- const char *name;
-
- fprintf (stderr, "Information about digests supported by the /dev/crypto"
- " engine:\n");
-#ifndef CIOCGSESSINFO
- fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
-#endif
-
- for (i = 0; i < OSSL_NELEM(digest_data); i++) {
- name = OBJ_nid2sn(digest_data[i].nid);
- fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
- name ? name : "unknown", digest_data[i].nid,
- digest_data[i].devcryptoid,
- digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
- if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
- fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
- continue;
- }
- if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
- fprintf(stderr, " (hw accelerated)");
- else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
- fprintf(stderr, " (software)");
- else
- fprintf(stderr, " (acceleration status unknown)");
- if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
- fprintf (stderr, ". Cipher setup failed\n");
- else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
- fprintf(stderr, ", CIOCCPHASH failed\n");
- else
- fprintf(stderr, ", CIOCCPHASH capable\n");
- }
- fprintf(stderr, "\n");
-}
-
-#endif
-
-/******************************************************************************
- *
- * CONTROL COMMANDS
- *
- *****/
-
-#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
-#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
-#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
-#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
-
-static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
-#if defined(CIOCGSESSINFO) || defined(CIOCGSESSION2)
- {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
- "USE_SOFTDRIVERS",
- "specifies whether to use software (not accelerated) drivers ("
- OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
- OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
- OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
- "=use if acceleration can't be determined) [default="
- OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]",
- ENGINE_CMD_FLAG_NUMERIC},
-#endif
-
- {DEVCRYPTO_CMD_CIPHERS,
- "CIPHERS",
- "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
- ENGINE_CMD_FLAG_STRING},
-
-#ifdef IMPLEMENT_DIGEST
- {DEVCRYPTO_CMD_DIGESTS,
- "DIGESTS",
- "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
- ENGINE_CMD_FLAG_STRING},
-#endif
-
- {DEVCRYPTO_CMD_DUMP_INFO,
- "DUMP_INFO",
- "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
- ENGINE_CMD_FLAG_NO_INPUT},
-
- {0, NULL, NULL, 0}
-};
-
-static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
-{
- int *new_list;
- switch (cmd) {
-#if defined(CIOCGSESSINFO) || defined(CIOCGSESSION2)
- case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
- switch (i) {
- case DEVCRYPTO_REQUIRE_ACCELERATED:
- case DEVCRYPTO_USE_SOFTWARE:
- case DEVCRYPTO_REJECT_SOFTWARE:
- break;
- default:
- fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
- return 0;
- }
- if (use_softdrivers == i)
- return 1;
- use_softdrivers = i;
-#ifdef IMPLEMENT_DIGEST
- rebuild_known_digest_nids(e);
-#endif
- rebuild_known_cipher_nids(e);
- return 1;
-#endif /* CIOCGSESSINFO || CIOCGSESSION2 */
-
- case DEVCRYPTO_CMD_CIPHERS:
- if (p == NULL)
- return 1;
- if (OPENSSL_strcasecmp((const char *)p, "ALL") == 0) {
- devcrypto_select_all_ciphers(selected_ciphers);
- } else if (OPENSSL_strcasecmp((const char*)p, "NONE") == 0) {
- memset(selected_ciphers, 0, sizeof(selected_ciphers));
- } else {
- new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
- if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
- OPENSSL_free(new_list);
- return 0;
- }
- memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
- OPENSSL_free(new_list);
- }
- rebuild_known_cipher_nids(e);
- return 1;
-
-#ifdef IMPLEMENT_DIGEST
- case DEVCRYPTO_CMD_DIGESTS:
- if (p == NULL)
- return 1;
- if (OPENSSL_strcasecmp((const char *)p, "ALL") == 0) {
- devcrypto_select_all_digests(selected_digests);
- } else if (OPENSSL_strcasecmp((const char*)p, "NONE") == 0) {
- memset(selected_digests, 0, sizeof(selected_digests));
- } else {
- new_list=OPENSSL_zalloc(sizeof(selected_digests));
- if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
- OPENSSL_free(new_list);
- return 0;
- }
- memcpy(selected_digests, new_list, sizeof(selected_digests));
- OPENSSL_free(new_list);
- }
- rebuild_known_digest_nids(e);
- return 1;
-#endif /* IMPLEMENT_DIGEST */
-
- case DEVCRYPTO_CMD_DUMP_INFO:
- dump_cipher_info();
-#ifdef IMPLEMENT_DIGEST
- dump_digest_info();
-#endif
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/******************************************************************************
- *
- * LOAD / UNLOAD
- *
- *****/
-
-/*
- * Opens /dev/crypto
- */
-static int open_devcrypto(void)
-{
- int fd;
-
- if (cfd >= 0)
- return 1;
-
- if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
-#ifndef ENGINE_DEVCRYPTO_DEBUG
- if (errno != ENOENT && errno != ENXIO)
-#endif
- fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
- return 0;
- }
-
-#ifdef CRIOGET
- if (ioctl(fd, CRIOGET, &cfd) < 0) {
- fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
- close(fd);
- cfd = -1;
- return 0;
- }
- close(fd);
-#else
- cfd = fd;
-#endif
-
- return 1;
-}
-
-static int close_devcrypto(void)
-{
- int ret;
-
- if (cfd < 0)
- return 1;
- ret = close(cfd);
- cfd = -1;
- if (ret != 0) {
- fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
- return 0;
- }
- return 1;
-}
-
-static int devcrypto_unload(ENGINE *e)
-{
- destroy_all_cipher_methods();
-#ifdef IMPLEMENT_DIGEST
- destroy_all_digest_methods();
-#endif
-
- close_devcrypto();
-
- return 1;
-}
-
-static int bind_devcrypto(ENGINE *e) {
-
- if (!ENGINE_set_id(e, engine_devcrypto_id)
- || !ENGINE_set_name(e, "/dev/crypto engine")
- || !ENGINE_set_destroy_function(e, devcrypto_unload)
- || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
- || !ENGINE_set_ctrl_function(e, devcrypto_ctrl))
- return 0;
-
- prepare_cipher_methods();
-#ifdef IMPLEMENT_DIGEST
- prepare_digest_methods();
-#endif
-
- return (ENGINE_set_ciphers(e, devcrypto_ciphers)
-#ifdef IMPLEMENT_DIGEST
- && ENGINE_set_digests(e, devcrypto_digests)
-#endif
-/*
- * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
- * implementations, it seems to only exist in FreeBSD, and regarding the
- * parameters in its crypt_kop, the manual crypto(4) has this to say:
- *
- * The semantics of these arguments are currently undocumented.
- *
- * Reading through the FreeBSD source code doesn't give much more than
- * their CRK_MOD_EXP implementation for ubsec.
- *
- * It doesn't look much better with cryptodev-linux. They have the crypt_kop
- * structure as well as the command (CRK_*) in cryptodev.h, but no support
- * seems to be implemented at all for the moment.
- *
- * At the time of writing, it seems impossible to write proper support for
- * FreeBSD's asym features without some very deep knowledge and access to
- * specific kernel modules.
- *
- * /Richard Levitte, 2017-05-11
- */
-#if 0
- && ENGINE_set_RSA(e, devcrypto_rsa)
-# ifndef OPENSSL_NO_DSA
- && ENGINE_set_DSA(e, devcrypto_dsa)
-# endif
-# ifndef OPENSSL_NO_DH
- && ENGINE_set_DH(e, devcrypto_dh)
-# endif
-# ifndef OPENSSL_NO_EC
- && ENGINE_set_EC(e, devcrypto_ec)
-# endif
-#endif
- );
-}
-
-/*
- * In case this engine is built into libcrypto, then it doesn't offer any
- * ability to be dynamically loadable.
- */
-void engine_load_devcrypto_int(void)
-{
- ENGINE *e = NULL;
-
- if (!open_devcrypto())
- return;
-
- if ((e = ENGINE_new()) == NULL
- || !bind_devcrypto(e)) {
- close_devcrypto();
- ENGINE_free(e);
- return;
- }
-
- ERR_set_mark();
- ENGINE_add(e);
- /*
- * If the "add" worked, it gets a structural reference. So either way, we
- * release our just-created reference.
- */
- ENGINE_free(e); /* Loose our local reference */
- /*
- * 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();
-}
+++ /dev/null
-/*
- * 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
- */
-
-/* THIS ENGINE IS FOR TESTING PURPOSES ONLY. */
-
-/* This file has quite some overlap with providers/implementations/storemgmt/file_store.c */
-
-/*
- * We need to use some asn1_meth deprecated APIs
- */
-#define OPENSSL_SUPPRESS_DEPRECATED
-
-#include "internal/e_os.h" /* for stat */
-#include <string.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include <openssl/bio.h>
-#include <openssl/dsa.h> /* For d2i_DSAPrivateKey */
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-#include <openssl/pkcs12.h> /* For the PKCS8 stuff o.O */
-#include <openssl/rsa.h> /* For d2i_RSAPrivateKey */
-#include <openssl/safestack.h>
-#include <openssl/store.h>
-#include <openssl/ui.h>
-#include <openssl/engine.h>
-#include <openssl/x509.h> /* For the PKCS8 stuff o.O */
-#include "internal/asn1.h" /* For asn1_d2i_read_bio */
-#include "internal/o_dir.h"
-#include "internal/cryptlib.h"
-#include "crypto/ctype.h" /* For ossl_isdigit */
-#include "crypto/pem.h" /* For PVK and "blob" PEM headers */
-
-/* clang-format off */
-#include "e_loader_attic_err.c"
-/* clang-format on */
-
-DEFINE_STACK_OF(OSSL_STORE_INFO)
-
-#ifndef S_ISDIR
-# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
-#endif
-
-/*-
- * Password prompting
- * ------------------
- */
-
-static char *file_get_pass(const UI_METHOD *ui_method, char *pass,
- size_t maxsize, const char *desc, const char *info,
- void *data)
-{
- UI *ui = UI_new();
- char *prompt = NULL;
-
- if (ui == NULL) {
- ATTICerr(0, ERR_R_UI_LIB);
- return NULL;
- }
-
- if (ui_method != NULL)
- UI_set_method(ui, ui_method);
- UI_add_user_data(ui, data);
-
- if ((prompt = UI_construct_prompt(ui, desc, info)) == NULL) {
- ATTICerr(0, ERR_R_UI_LIB);
- pass = NULL;
- } else if (UI_add_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD,
- pass, 0, (int)(maxsize - 1)) <= 0) {
- ATTICerr(0, ERR_R_UI_LIB);
- pass = NULL;
- } else {
- switch (UI_process(ui)) {
- case -2:
- ATTICerr(0, ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED);
- pass = NULL;
- break;
- case -1:
- ATTICerr(0, ERR_R_UI_LIB);
- pass = NULL;
- break;
- default:
- break;
- }
- }
-
- OPENSSL_free(prompt);
- UI_free(ui);
- return pass;
-}
-
-struct pem_pass_data {
- const UI_METHOD *ui_method;
- void *data;
- const char *prompt_desc;
- const char *prompt_info;
-};
-
-static int file_fill_pem_pass_data(struct pem_pass_data *pass_data,
- const char *desc, const char *info,
- const UI_METHOD *ui_method, void *ui_data)
-{
- if (pass_data == NULL)
- return 0;
- pass_data->ui_method = ui_method;
- pass_data->data = ui_data;
- pass_data->prompt_desc = desc;
- pass_data->prompt_info = info;
- return 1;
-}
-
-/* This is used anywhere a pem_password_cb is needed */
-static int file_get_pem_pass(char *buf, int num, int w, void *data)
-{
- struct pem_pass_data *pass_data = data;
- char *pass = file_get_pass(pass_data->ui_method, buf, num,
- pass_data->prompt_desc, pass_data->prompt_info,
- pass_data->data);
-
- return pass == NULL ? 0 : (int)strlen(pass);
-}
-
-/*
- * Check if |str| ends with |suffix| preceded by a space, and if it does,
- * return the index of that space. If there is no such suffix in |str|,
- * return -1.
- * For |str| == "FOO BAR" and |suffix| == "BAR", the returned value is 3.
- */
-static int check_suffix(const char *str, const char *suffix)
-{
- int str_len = (int)strlen(str);
- int suffix_len = (int)(strlen(suffix) + 1);
- const char *p = NULL;
-
- if (suffix_len >= str_len)
- return -1;
- p = str + str_len - suffix_len;
- if (*p != ' '
- || strcmp(p + 1, suffix) != 0)
- return -1;
- return (int)(p - str);
-}
-
-/*
- * EMBEDDED is a special type of OSSL_STORE_INFO, specially for the file
- * handlers, so we define it internally. This uses the possibility to
- * create an OSSL_STORE_INFO with a generic data pointer and arbitrary
- * type number.
- *
- * This is used by a FILE_HANDLER's try_decode function to signal that it
- * has decoded the incoming blob into a new blob, and that the attempted
- * decoding should be immediately restarted with the new blob, using the
- * new PEM name.
- */
-/* Negative numbers are never used for public OSSL_STORE_INFO types */
-#define STORE_INFO_EMBEDDED -1
-
-/* This is the embedded data */
-struct embedded_st {
- BUF_MEM *blob;
- char *pem_name;
-};
-
-/* Helper functions */
-static struct embedded_st *get0_EMBEDDED(OSSL_STORE_INFO *info)
-{
- return OSSL_STORE_INFO_get0_data(STORE_INFO_EMBEDDED, info);
-}
-
-static void store_info_free(OSSL_STORE_INFO *info)
-{
- struct embedded_st *data;
-
- if (info != NULL && (data = get0_EMBEDDED(info)) != NULL) {
- BUF_MEM_free(data->blob);
- OPENSSL_free(data->pem_name);
- OPENSSL_free(data);
- }
- OSSL_STORE_INFO_free(info);
-}
-
-static OSSL_STORE_INFO *new_EMBEDDED(const char *new_pem_name,
- BUF_MEM *embedded)
-{
- OSSL_STORE_INFO *info = NULL;
- struct embedded_st *data = NULL;
-
- if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL)
- return NULL;
- if ((info = OSSL_STORE_INFO_new(STORE_INFO_EMBEDDED, data)) == NULL) {
- ATTICerr(0, ERR_R_OSSL_STORE_LIB);
- OPENSSL_free(data);
- return NULL;
- }
-
- data->blob = embedded;
- data->pem_name =
- new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name);
-
- if (new_pem_name != NULL && data->pem_name == NULL) {
- store_info_free(info);
- info = NULL;
- }
-
- return info;
-}
-
-/*-
- * The file scheme decoders
- * ------------------------
- *
- * Each possible data type has its own decoder, which either operates
- * through a given PEM name, or attempts to decode to see if the blob
- * it's given is decodable for its data type. The assumption is that
- * only the correct data type will match the content.
- */
-
-/*-
- * The try_decode function is called to check if the blob of data can
- * be used by this handler, and if it can, decodes it into a supported
- * OpenSSL type and returns an OSSL_STORE_INFO with the decoded data.
- * Input:
- * pem_name: If this blob comes from a PEM file, this holds
- * the PEM name. If it comes from another type of
- * file, this is NULL.
- * pem_header: If this blob comes from a PEM file, this holds
- * the PEM headers. If it comes from another type of
- * file, this is NULL.
- * blob: The blob of data to match with what this handler
- * can use.
- * len: The length of the blob.
- * handler_ctx: For a handler marked repeatable, this pointer can
- * be used to create a context for the handler. IT IS
- * THE HANDLER'S RESPONSIBILITY TO CREATE AND DESTROY
- * THIS CONTEXT APPROPRIATELY, i.e. create on first call
- * and destroy when about to return NULL.
- * matchcount: A pointer to an int to count matches for this data.
- * Usually becomes 0 (no match) or 1 (match!), but may
- * be higher in the (unlikely) event that the data matches
- * more than one possibility. The int will always be
- * zero when the function is called.
- * ui_method: Application UI method for getting a password, pin
- * or any other interactive data.
- * ui_data: Application data to be passed to ui_method when
- * it's called.
- * libctx: The library context to be used if applicable
- * propq: The property query string for any algorithm fetches
- * Output:
- * an OSSL_STORE_INFO
- */
-typedef OSSL_STORE_INFO *(*file_try_decode_fn)(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **handler_ctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data, const char *uri,
- OSSL_LIB_CTX *libctx,
- const char *propq);
-/*
- * The eof function should return 1 if there's no more data to be found
- * with the handler_ctx, otherwise 0. This is only used when the handler is
- * marked repeatable.
- */
-typedef int (*file_eof_fn)(void *handler_ctx);
-/*
- * The destroy_ctx function is used to destroy the handler_ctx that was
- * initiated by a repeatable try_decode function. This is only used when
- * the handler is marked repeatable.
- */
-typedef void (*file_destroy_ctx_fn)(void **handler_ctx);
-
-typedef struct file_handler_st {
- const char *name;
- file_try_decode_fn try_decode;
- file_eof_fn eof;
- file_destroy_ctx_fn destroy_ctx;
-
- /* flags */
- int repeatable;
-} FILE_HANDLER;
-
-/*
- * PKCS#12 decoder. It operates by decoding all of the blob content,
- * extracting all the interesting data from it and storing them internally,
- * then serving them one piece at a time.
- */
-static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data, const char *uri,
- OSSL_LIB_CTX *libctx,
- const char *propq)
-{
- OSSL_STORE_INFO *store_info = NULL;
- STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;
-
- if (ctx == NULL) {
- /* Initial parsing */
- PKCS12 *p12;
-
- if (pem_name != NULL || len > LONG_MAX)
- /* No match, there is no PEM PKCS12 tag */
- return NULL;
-
- if ((p12 = d2i_PKCS12(NULL, &blob, (long)len)) != NULL) {
- char *pass = NULL;
- char tpass[PEM_BUFSIZE];
- EVP_PKEY *pkey = NULL;
- X509 *cert = NULL;
- STACK_OF(X509) *chain = NULL;
-
- *matchcount = 1;
-
- if (!PKCS12_mac_present(p12)
- || PKCS12_verify_mac(p12, "", 0)
- || PKCS12_verify_mac(p12, NULL, 0)) {
- pass = "";
- } else {
- if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE,
- "PKCS12 import", uri,
- ui_data)) == NULL) {
- ATTICerr(0, ATTIC_R_PASSPHRASE_CALLBACK_ERROR);
- goto p12_end;
- }
- if (!PKCS12_verify_mac(p12, pass, (int)strlen(pass))) {
- ATTICerr(0, ATTIC_R_ERROR_VERIFYING_PKCS12_MAC);
- goto p12_end;
- }
- }
-
- if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) {
- OSSL_STORE_INFO *osi_pkey = NULL;
- OSSL_STORE_INFO *osi_cert = NULL;
- OSSL_STORE_INFO *osi_ca = NULL;
- int ok = 1;
-
- if ((ctx = sk_OSSL_STORE_INFO_new_null()) != NULL) {
- if (pkey != NULL) {
- if ((osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL
- /* clearing pkey here avoids case distinctions */
- && (pkey = NULL) == NULL
- && sk_OSSL_STORE_INFO_push(ctx, osi_pkey) != 0)
- osi_pkey = NULL;
- else
- ok = 0;
- }
- if (ok && cert != NULL) {
- if ((osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL
- /* clearing cert here avoids case distinctions */
- && (cert = NULL) == NULL
- && sk_OSSL_STORE_INFO_push(ctx, osi_cert) != 0)
- osi_cert = NULL;
- else
- ok = 0;
- }
- while (ok && sk_X509_num(chain) > 0) {
- X509 *ca = sk_X509_value(chain, 0);
-
- if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) != NULL
- && sk_X509_shift(chain) != NULL
- && sk_OSSL_STORE_INFO_push(ctx, osi_ca) != 0)
- osi_ca = NULL;
- else
- ok = 0;
- }
- }
- EVP_PKEY_free(pkey);
- X509_free(cert);
- OSSL_STACK_OF_X509_free(chain);
- store_info_free(osi_pkey);
- store_info_free(osi_cert);
- store_info_free(osi_ca);
- if (!ok) {
- sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free);
- ctx = NULL;
- }
- *pctx = ctx;
- }
- }
- p12_end:
- PKCS12_free(p12);
- if (ctx == NULL)
- return NULL;
- }
-
- *matchcount = 1;
- store_info = sk_OSSL_STORE_INFO_shift(ctx);
- return store_info;
-}
-
-static int eof_PKCS12(void *ctx_)
-{
- STACK_OF(OSSL_STORE_INFO) *ctx = ctx_;
-
- return ctx == NULL || sk_OSSL_STORE_INFO_num(ctx) == 0;
-}
-
-static void destroy_ctx_PKCS12(void **pctx)
-{
- STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;
-
- sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free);
- *pctx = NULL;
-}
-
-static FILE_HANDLER PKCS12_handler = {
- "PKCS12",
- try_decode_PKCS12,
- eof_PKCS12,
- destroy_ctx_PKCS12,
- 1 /* repeatable */
-};
-
-/*
- * Encrypted PKCS#8 decoder. It operates by just decrypting the given blob
- * into a new blob, which is returned as an EMBEDDED STORE_INFO. The whole
- * decoding process will then start over with the new blob.
- */
-static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data,
- const char *uri,
- OSSL_LIB_CTX *libctx,
- const char *propq)
-{
- X509_SIG *p8 = NULL;
- char kbuf[PEM_BUFSIZE];
- char *pass = NULL;
- const X509_ALGOR *dalg = NULL;
- const ASN1_OCTET_STRING *doct = NULL;
- OSSL_STORE_INFO *store_info = NULL;
- BUF_MEM *mem = NULL;
- unsigned char *new_data = NULL;
- int new_data_len;
-
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_PKCS8) != 0)
- return NULL;
- *matchcount = 1;
- }
-
- if (len > LONG_MAX || (p8 = d2i_X509_SIG(NULL, &blob, (long)len)) == NULL)
- return NULL;
-
- *matchcount = 1;
-
- if ((mem = BUF_MEM_new()) == NULL) {
- ATTICerr(0, ERR_R_BUF_LIB);
- goto nop8;
- }
-
- if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE,
- "PKCS8 decrypt pass phrase", uri,
- ui_data)) == NULL) {
- ATTICerr(0, ATTIC_R_BAD_PASSWORD_READ);
- goto nop8;
- }
-
- X509_SIG_get0(p8, &dalg, &doct);
- if (!PKCS12_pbe_crypt(dalg, pass, (int)strlen(pass),
- doct->data, doct->length,
- &new_data, &new_data_len, 0))
- goto nop8;
-
- mem->data = (char *)new_data;
- mem->max = mem->length = (size_t)new_data_len;
- X509_SIG_free(p8);
- p8 = NULL;
-
- store_info = new_EMBEDDED(PEM_STRING_PKCS8INF, mem);
- if (store_info == NULL) {
- ATTICerr(0, ERR_R_OSSL_STORE_LIB);
- goto nop8;
- }
-
- return store_info;
- nop8:
- X509_SIG_free(p8);
- BUF_MEM_free(mem);
- return NULL;
-}
-
-static FILE_HANDLER PKCS8Encrypted_handler = {
- "PKCS8Encrypted",
- try_decode_PKCS8Encrypted
-};
-
-/*
- * Private key decoder. Decodes all sorts of private keys, both PKCS#8
- * encoded ones and old style PEM ones (with the key type is encoded into
- * the PEM name).
- */
-static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data, const char *uri,
- OSSL_LIB_CTX *libctx,
- const char *propq)
-{
- OSSL_STORE_INFO *store_info = NULL;
- EVP_PKEY *pkey = NULL;
- const EVP_PKEY_ASN1_METHOD *ameth = NULL;
-
- if (len > LONG_MAX)
- return NULL;
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_PKCS8INF) == 0) {
- PKCS8_PRIV_KEY_INFO *p8inf =
- d2i_PKCS8_PRIV_KEY_INFO(NULL, &blob, (long)len);
-
- *matchcount = 1;
- if (p8inf != NULL)
- pkey = EVP_PKCS82PKEY_ex(p8inf, libctx, propq);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- } else {
- int slen;
- int pkey_id;
-
- if ((slen = check_suffix(pem_name, "PRIVATE KEY")) > 0
- && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name,
- slen)) != NULL
- && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
- ameth)) {
- *matchcount = 1;
- pkey = d2i_PrivateKey_ex(pkey_id, NULL, &blob, (long)len,
- libctx, propq);
- }
- }
- } else {
- int i;
-
- for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
- EVP_PKEY *tmp_pkey = NULL;
- const unsigned char *tmp_blob = blob;
- int pkey_id, pkey_flags;
-
- ameth = EVP_PKEY_asn1_get0(i);
- if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL,
- NULL, ameth)
- || (pkey_flags & ASN1_PKEY_ALIAS) != 0)
- continue;
-
- ERR_set_mark(); /* prevent flooding error queue */
- tmp_pkey = d2i_PrivateKey_ex(pkey_id, NULL, &tmp_blob, (long)len,
- libctx, propq);
- if (tmp_pkey != NULL) {
- if (pkey != NULL)
- EVP_PKEY_free(tmp_pkey);
- else
- pkey = tmp_pkey;
- (*matchcount)++;
- }
- ERR_pop_to_mark();
- }
-
- if (*matchcount > 1) {
- EVP_PKEY_free(pkey);
- pkey = NULL;
- }
- }
- if (pkey == NULL)
- /* No match */
- return NULL;
-
- store_info = OSSL_STORE_INFO_new_PKEY(pkey);
- if (store_info == NULL)
- EVP_PKEY_free(pkey);
-
- return store_info;
-}
-
-static FILE_HANDLER PrivateKey_handler = {
- "PrivateKey",
- try_decode_PrivateKey
-};
-
-/*
- * Public key decoder. Only supports SubjectPublicKeyInfo formatted keys.
- */
-static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data, const char *uri,
- OSSL_LIB_CTX *libctx,
- const char *propq)
-{
- OSSL_STORE_INFO *store_info = NULL;
- EVP_PKEY *pkey = NULL;
-
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_PUBLIC) != 0)
- /* No match */
- return NULL;
- *matchcount = 1;
- }
-
- if (len > LONG_MAX || (pkey = d2i_PUBKEY(NULL, &blob, (long)len)) != NULL) {
- *matchcount = 1;
- store_info = OSSL_STORE_INFO_new_PUBKEY(pkey);
- }
-
- return store_info;
-}
-
-static FILE_HANDLER PUBKEY_handler = {
- "PUBKEY",
- try_decode_PUBKEY
-};
-
-/*
- * Key parameter decoder.
- */
-static OSSL_STORE_INFO *try_decode_params(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data, const char *uri,
- OSSL_LIB_CTX *libctx,
- const char *propq)
-{
- OSSL_STORE_INFO *store_info = NULL;
- EVP_PKEY *pkey = NULL;
- const EVP_PKEY_ASN1_METHOD *ameth = NULL;
-
- if (len > LONG_MAX)
- return NULL;
- if (pem_name != NULL) {
- int slen;
- int pkey_id;
-
- if ((slen = check_suffix(pem_name, "PARAMETERS")) > 0
- && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, slen)) != NULL
- && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
- ameth)) {
- *matchcount = 1;
- pkey = d2i_KeyParams(pkey_id, NULL, &blob, (long)len);
- }
- } else {
- int i;
-
- for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
- EVP_PKEY *tmp_pkey = NULL;
- const unsigned char *tmp_blob = blob;
- int pkey_id, pkey_flags;
-
- ameth = EVP_PKEY_asn1_get0(i);
- if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL,
- NULL, ameth)
- || (pkey_flags & ASN1_PKEY_ALIAS) != 0)
- continue;
-
- ERR_set_mark(); /* prevent flooding error queue */
-
- tmp_pkey = d2i_KeyParams(pkey_id, NULL, &tmp_blob, (long)len);
-
- if (tmp_pkey != NULL) {
- if (pkey != NULL)
- EVP_PKEY_free(tmp_pkey);
- else
- pkey = tmp_pkey;
- (*matchcount)++;
- }
- ERR_pop_to_mark();
- }
-
- if (*matchcount > 1) {
- EVP_PKEY_free(pkey);
- pkey = NULL;
- }
- }
- if (pkey == NULL)
- /* No match */
- return NULL;
-
- store_info = OSSL_STORE_INFO_new_PARAMS(pkey);
- if (store_info == NULL)
- EVP_PKEY_free(pkey);
-
- return store_info;
-}
-
-static FILE_HANDLER params_handler = {
- "params",
- try_decode_params
-};
-
-/*
- * X.509 certificate decoder.
- */
-static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data,
- const char *uri,
- OSSL_LIB_CTX *libctx,
- const char *propq)
-{
- OSSL_STORE_INFO *store_info = NULL;
- X509 *cert = NULL;
-
- /*
- * In most cases, we can try to interpret the serialized data as a trusted
- * cert (X509 + X509_AUX) and fall back to reading it as a normal cert
- * (just X509), but if the PEM name specifically declares it as a trusted
- * cert, then no fallback should be engaged. |ignore_trusted| tells if
- * the fallback can be used (1) or not (0).
- */
- int ignore_trusted = 1;
-
- if (len > LONG_MAX)
- return NULL;
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_X509_TRUSTED) == 0)
- ignore_trusted = 0;
- else if (strcmp(pem_name, PEM_STRING_X509_OLD) != 0
- && strcmp(pem_name, PEM_STRING_X509) != 0)
- /* No match */
- return NULL;
- *matchcount = 1;
- }
-
- cert = X509_new_ex(libctx, propq);
- if (cert == NULL)
- return NULL;
-
- if ((d2i_X509_AUX(&cert, &blob, (long)len)) != NULL
- || (ignore_trusted && (d2i_X509(&cert, &blob, (long)len)) != NULL)) {
- *matchcount = 1;
- store_info = OSSL_STORE_INFO_new_CERT(cert);
- }
-
- if (store_info == NULL)
- X509_free(cert);
-
- return store_info;
-}
-
-static FILE_HANDLER X509Certificate_handler = {
- "X509Certificate",
- try_decode_X509Certificate
-};
-
-/*
- * X.509 CRL decoder.
- */
-static OSSL_STORE_INFO *try_decode_X509CRL(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data, const char *uri,
- OSSL_LIB_CTX *libctx,
- const char *propq)
-{
- OSSL_STORE_INFO *store_info = NULL;
- X509_CRL *crl = NULL;
-
- if (len > LONG_MAX)
- return NULL;
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_X509_CRL) != 0)
- /* No match */
- return NULL;
- *matchcount = 1;
- }
-
- if ((crl = d2i_X509_CRL(NULL, &blob, (long)len)) != NULL) {
- *matchcount = 1;
- store_info = OSSL_STORE_INFO_new_CRL(crl);
- }
-
- if (store_info == NULL)
- X509_CRL_free(crl);
-
- return store_info;
-}
-
-static FILE_HANDLER X509CRL_handler = {
- "X509CRL",
- try_decode_X509CRL
-};
-
-/*
- * To finish it all off, we collect all the handlers.
- */
-static const FILE_HANDLER *file_handlers[] = {
- &PKCS12_handler,
- &PKCS8Encrypted_handler,
- &X509Certificate_handler,
- &X509CRL_handler,
- ¶ms_handler,
- &PUBKEY_handler,
- &PrivateKey_handler,
-};
-
-
-/*-
- * The loader itself
- * -----------------
- */
-
-struct ossl_store_loader_ctx_st {
- char *uri; /* The URI we currently try to load */
- enum {
- is_raw = 0,
- is_pem,
- is_dir
- } type;
- int errcnt;
-#define FILE_FLAG_SECMEM (1<<0)
-#define FILE_FLAG_ATTACHED (1<<1)
- unsigned int flags;
- union {
- struct { /* Used with is_raw and is_pem */
- BIO *file;
-
- /*
- * The following are used when the handler is marked as
- * repeatable
- */
- const FILE_HANDLER *last_handler;
- void *last_handler_ctx;
- } file;
- struct { /* Used with is_dir */
- OPENSSL_DIR_CTX *ctx;
- int end_reached;
-
- /*
- * When a search expression is given, these are filled in.
- * |search_name| contains the file basename to look for.
- * The string is exactly 8 characters long.
- */
- char search_name[9];
-
- /*
- * The directory reading utility we have combines opening with
- * reading the first name. To make sure we can detect the end
- * at the right time, we read early and cache the name.
- */
- const char *last_entry;
- int last_errno;
- } dir;
- } _;
-
- /* Expected object type. May be unspecified */
- int expected_type;
-
- OSSL_LIB_CTX *libctx;
- char *propq;
-};
-
-static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
-{
- if (ctx == NULL)
- return;
-
- OPENSSL_free(ctx->propq);
- OPENSSL_free(ctx->uri);
- if (ctx->type != is_dir) {
- if (ctx->_.file.last_handler != NULL) {
- ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx);
- ctx->_.file.last_handler_ctx = NULL;
- ctx->_.file.last_handler = NULL;
- }
- }
- OPENSSL_free(ctx);
-}
-
-static int file_find_type(OSSL_STORE_LOADER_CTX *ctx)
-{
- BIO *buff = NULL;
- char peekbuf[4096] = { 0, };
-
- if ((buff = BIO_new(BIO_f_buffer())) == NULL)
- return 0;
-
- ctx->_.file.file = BIO_push(buff, ctx->_.file.file);
- if (BIO_buffer_peek(ctx->_.file.file, peekbuf, sizeof(peekbuf) - 1) > 0) {
- peekbuf[sizeof(peekbuf) - 1] = '\0';
- if (strstr(peekbuf, "-----BEGIN ") != NULL)
- ctx->type = is_pem;
- }
- return 1;
-}
-
-static OSSL_STORE_LOADER_CTX *file_open_ex
- (const OSSL_STORE_LOADER *loader, const char *uri,
- OSSL_LIB_CTX *libctx, const char *propq,
- const UI_METHOD *ui_method, void *ui_data)
-{
- OSSL_STORE_LOADER_CTX *ctx = NULL;
- struct stat st;
- const char *path_data[2];
- size_t path_data_n = 0, i;
- const char *path, *p = uri, *q;
-
- /*
- * First step, just take the URI as is.
- */
- path_data[path_data_n++] = uri;
-
- /*
- * Second step, if the URI appears to start with the "file" scheme,
- * extract the path and make that the second path to check.
- * There's a special case if the URI also contains an authority, then
- * the full URI shouldn't be used as a path anywhere.
- */
- if (CHECK_AND_SKIP_CASE_PREFIX(p, "file:")) {
- q = p;
- if (CHECK_AND_SKIP_PREFIX(q, "//")) {
- path_data_n--; /* Invalidate using the full URI */
- if (CHECK_AND_SKIP_CASE_PREFIX(q, "localhost/")
- || CHECK_AND_SKIP_PREFIX(q, "/")) {
- /*
- * In this case, we step back on char to ensure that the
- * first slash is preserved, making the path always absolute
- */
- p = q - 1;
- } else {
- ATTICerr(0, ATTIC_R_URI_AUTHORITY_UNSUPPORTED);
- return NULL;
- }
- }
-#ifdef _WIN32
- /* Windows "file:" URIs with a drive letter start with a '/' */
- if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
- char c = tolower((unsigned char)p[1]);
-
- if (c >= 'a' && c <= 'z') {
- /* Skip past the slash, making the path a normal Windows path */
- p++;
- }
- }
-#endif
- path_data[path_data_n++] = p;
- }
-
-
- for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) {
- if (stat(path_data[i], &st) < 0) {
- ERR_raise_data(ERR_LIB_SYS, errno,
- "calling stat(%s)",
- path_data[i]);
- } else {
- path = path_data[i];
- }
- }
- if (path == NULL) {
- return NULL;
- }
-
- /* Successfully found a working path */
-
- ctx = OPENSSL_zalloc(sizeof(*ctx));
- if (ctx == NULL)
- return NULL;
- ctx->uri = OPENSSL_strdup(uri);
- if (ctx->uri == NULL)
- goto err;
-
- if (S_ISDIR(st.st_mode)) {
- ctx->type = is_dir;
- ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, path);
- ctx->_.dir.last_errno = errno;
- if (ctx->_.dir.last_entry == NULL) {
- if (ctx->_.dir.last_errno != 0) {
- ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
- goto err;
- }
- ctx->_.dir.end_reached = 1;
- }
- } else if ((ctx->_.file.file = BIO_new_file(path, "rb")) == NULL
- || !file_find_type(ctx)) {
- BIO_free_all(ctx->_.file.file);
- goto err;
- }
- if (propq != NULL) {
- ctx->propq = OPENSSL_strdup(propq);
- if (ctx->propq == NULL)
- goto err;
- }
- ctx->libctx = libctx;
-
- return ctx;
- err:
- OSSL_STORE_LOADER_CTX_free(ctx);
- return NULL;
-}
-
-static OSSL_STORE_LOADER_CTX *file_open
- (const OSSL_STORE_LOADER *loader, const char *uri,
- const UI_METHOD *ui_method, void *ui_data)
-{
- return file_open_ex(loader, uri, NULL, NULL, ui_method, ui_data);
-}
-
-static OSSL_STORE_LOADER_CTX *file_attach
- (const OSSL_STORE_LOADER *loader, BIO *bp,
- OSSL_LIB_CTX *libctx, const char *propq,
- const UI_METHOD *ui_method, void *ui_data)
-{
- OSSL_STORE_LOADER_CTX *ctx = NULL;
-
- if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL
- || (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)) {
- OSSL_STORE_LOADER_CTX_free(ctx);
- return NULL;
- }
- ctx->libctx = libctx;
- ctx->flags |= FILE_FLAG_ATTACHED;
- ctx->_.file.file = bp;
- if (!file_find_type(ctx)) {
- /* Safety measure */
- ctx->_.file.file = NULL;
- goto err;
- }
- return ctx;
-err:
- OSSL_STORE_LOADER_CTX_free(ctx);
- return NULL;
-}
-
-static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args)
-{
- int ret = 1;
-
- switch (cmd) {
- case OSSL_STORE_C_USE_SECMEM:
- {
- int on = *(va_arg(args, int *));
-
- switch (on) {
- case 0:
- ctx->flags &= ~FILE_FLAG_SECMEM;
- break;
- case 1:
- ctx->flags |= FILE_FLAG_SECMEM;
- break;
- default:
- ATTICerr(0, ERR_R_PASSED_INVALID_ARGUMENT);
- ret = 0;
- break;
- }
- }
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static int file_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
-{
- ctx->expected_type = expected;
- return 1;
-}
-
-static int file_find(OSSL_STORE_LOADER_CTX *ctx,
- const OSSL_STORE_SEARCH *search)
-{
- /*
- * If ctx == NULL, the library is looking to know if this loader supports
- * the given search type.
- */
-
- if (OSSL_STORE_SEARCH_get_type(search) == OSSL_STORE_SEARCH_BY_NAME) {
- unsigned long hash = 0;
-
- if (ctx == NULL)
- return 1;
-
- if (ctx->type != is_dir) {
- ATTICerr(0, ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES);
- return 0;
- }
-
- hash = X509_NAME_hash_ex(OSSL_STORE_SEARCH_get0_name(search),
- NULL, NULL, NULL);
- BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name),
- "%08lx", hash);
- return 1;
- }
-
- if (ctx != NULL)
- ATTICerr(0, ATTIC_R_UNSUPPORTED_SEARCH_TYPE);
- return 0;
-}
-
-static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx,
- const char *pem_name,
- const char *pem_header,
- unsigned char *data, size_t len,
- const UI_METHOD *ui_method,
- void *ui_data, int *matchcount)
-{
- OSSL_STORE_INFO *result = NULL;
- BUF_MEM *new_mem = NULL;
- char *new_pem_name = NULL;
- int t = 0;
-
- again:
- {
- size_t i = 0;
- void *handler_ctx = NULL;
- const FILE_HANDLER **matching_handlers =
- OPENSSL_zalloc(sizeof(*matching_handlers)
- * OSSL_NELEM(file_handlers));
-
- if (matching_handlers == NULL)
- goto err;
-
- *matchcount = 0;
- for (i = 0; i < OSSL_NELEM(file_handlers); i++) {
- const FILE_HANDLER *handler = file_handlers[i];
- int try_matchcount = 0;
- void *tmp_handler_ctx = NULL;
- OSSL_STORE_INFO *tmp_result;
- unsigned long err;
-
- ERR_set_mark();
- tmp_result =
- handler->try_decode(pem_name, pem_header, data, len,
- &tmp_handler_ctx, &try_matchcount,
- ui_method, ui_data, ctx->uri,
- ctx->libctx, ctx->propq);
- /* avoid flooding error queue with low-level ASN.1 parse errors */
- err = ERR_peek_last_error();
- if (ERR_GET_LIB(err) == ERR_LIB_ASN1
- && ERR_GET_REASON(err) == ERR_R_NESTED_ASN1_ERROR)
- ERR_pop_to_mark();
- else
- ERR_clear_last_mark();
-
- if (try_matchcount > 0) {
-
- matching_handlers[*matchcount] = handler;
-
- if (handler_ctx)
- handler->destroy_ctx(&handler_ctx);
- handler_ctx = tmp_handler_ctx;
-
- if ((*matchcount += try_matchcount) > 1) {
- /* more than one match => ambiguous, kill any result */
- store_info_free(result);
- store_info_free(tmp_result);
- if (handler->destroy_ctx != NULL)
- handler->destroy_ctx(&handler_ctx);
- handler_ctx = NULL;
- tmp_result = NULL;
- result = NULL;
- }
- if (result == NULL)
- result = tmp_result;
- if (result == NULL) /* e.g., PKCS#12 file decryption error */
- break;
- }
- }
-
- if (result != NULL
- && *matchcount == 1 && matching_handlers[0]->repeatable) {
- ctx->_.file.last_handler = matching_handlers[0];
- ctx->_.file.last_handler_ctx = handler_ctx;
- }
-
- OPENSSL_free(matching_handlers);
- }
-
- err:
- OPENSSL_free(new_pem_name);
- BUF_MEM_free(new_mem);
-
- if (result != NULL
- && (t = OSSL_STORE_INFO_get_type(result)) == STORE_INFO_EMBEDDED) {
- struct embedded_st *embedded = get0_EMBEDDED(result);
-
- /* "steal" the embedded data */
- pem_name = new_pem_name = embedded->pem_name;
- new_mem = embedded->blob;
- data = (unsigned char *)new_mem->data;
- len = new_mem->length;
- embedded->pem_name = NULL;
- embedded->blob = NULL;
-
- store_info_free(result);
- result = NULL;
- goto again;
- }
-
- return result;
-}
-
-static OSSL_STORE_INFO *file_load_try_repeat(OSSL_STORE_LOADER_CTX *ctx,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_INFO *result = NULL;
- int try_matchcount = 0;
-
- if (ctx->_.file.last_handler != NULL) {
- result =
- ctx->_.file.last_handler->try_decode(NULL, NULL, NULL, 0,
- &ctx->_.file.last_handler_ctx,
- &try_matchcount,
- ui_method, ui_data, ctx->uri,
- ctx->libctx, ctx->propq);
-
- if (result == NULL) {
- ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx);
- ctx->_.file.last_handler_ctx = NULL;
- ctx->_.file.last_handler = NULL;
- }
- }
- return result;
-}
-
-static void pem_free_flag(void *pem_data, int secure, size_t num)
-{
- if (secure)
- OPENSSL_secure_clear_free(pem_data, num);
- else
- OPENSSL_free(pem_data);
-}
-static int file_read_pem(BIO *bp, char **pem_name, char **pem_header,
- unsigned char **data, long *len,
- const UI_METHOD *ui_method, void *ui_data,
- const char *uri, int secure)
-{
- int i = secure
- ? PEM_read_bio_ex(bp, pem_name, pem_header, data, len,
- PEM_FLAG_SECURE | PEM_FLAG_EAY_COMPATIBLE)
- : PEM_read_bio(bp, pem_name, pem_header, data, len);
-
- if (i <= 0)
- return 0;
-
- /*
- * 10 is the number of characters in "Proc-Type:", which
- * PEM_get_EVP_CIPHER_INFO() requires to be present.
- * If the PEM header has less characters than that, it's
- * not worth spending cycles on it.
- */
- if (strlen(*pem_header) > 10) {
- EVP_CIPHER_INFO cipher;
- struct pem_pass_data pass_data;
-
- if (!PEM_get_EVP_CIPHER_INFO(*pem_header, &cipher)
- || !file_fill_pem_pass_data(&pass_data, "PEM pass phrase", uri,
- ui_method, ui_data)
- || !PEM_do_header(&cipher, *data, len, file_get_pem_pass,
- &pass_data)) {
- return 0;
- }
- }
- return 1;
-}
-
-static OSSL_STORE_INFO *file_try_read_msblob(BIO *bp, int *matchcount)
-{
- OSSL_STORE_INFO *result = NULL;
- int ispub = -1;
-
- {
- unsigned int magic = 0, bitlen = 0;
- int isdss = 0;
- unsigned char peekbuf[16] = { 0, };
- const unsigned char *p = peekbuf;
-
- if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0)
- return 0;
- if (ossl_do_blob_header(&p, sizeof(peekbuf), &magic, &bitlen,
- &isdss, &ispub) <= 0)
- return 0;
- }
-
- (*matchcount)++;
-
- {
- EVP_PKEY *tmp = ispub
- ? b2i_PublicKey_bio(bp)
- : b2i_PrivateKey_bio(bp);
-
- if (tmp == NULL
- || (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) {
- EVP_PKEY_free(tmp);
- return 0;
- }
- }
-
- return result;
-}
-
-static OSSL_STORE_INFO *file_try_read_PVK(BIO *bp, const UI_METHOD *ui_method,
- void *ui_data, const char *uri,
- int *matchcount)
-{
- OSSL_STORE_INFO *result = NULL;
-
- {
- unsigned int saltlen = 0, keylen = 0;
- int isdss = -1;
- unsigned char peekbuf[24] = { 0, };
- const unsigned char *p = peekbuf;
-
- if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0)
- return 0;
- if (!ossl_do_PVK_header(&p, sizeof(peekbuf), 0, &isdss, &saltlen, &keylen))
- return 0;
- }
-
- (*matchcount)++;
-
- {
- EVP_PKEY *tmp = NULL;
- struct pem_pass_data pass_data;
-
- if (!file_fill_pem_pass_data(&pass_data, "PVK pass phrase", uri,
- ui_method, ui_data)
- || (tmp = b2i_PVK_bio(bp, file_get_pem_pass, &pass_data)) == NULL
- || (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) {
- EVP_PKEY_free(tmp);
- return 0;
- }
- }
-
- return result;
-}
-
-static int file_read_asn1(BIO *bp, unsigned char **data, long *len)
-{
- BUF_MEM *mem = NULL;
-
- if (asn1_d2i_read_bio(bp, &mem) < 0)
- return 0;
-
- *data = (unsigned char *)mem->data;
- *len = (long)mem->length;
- OPENSSL_free(mem);
-
- return 1;
-}
-
-static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name,
- char **data)
-{
- assert(name != NULL);
- assert(data != NULL);
- {
- const char *pathsep = ossl_ends_with_dirsep(ctx->uri) ? "" : "/";
- long calculated_length = (long)(strlen(ctx->uri) + strlen(pathsep)
- + strlen(name) + 1 /* \0 */);
-
- *data = OPENSSL_zalloc(calculated_length);
- if (*data == NULL)
- return 0;
-
- OPENSSL_strlcat(*data, ctx->uri, calculated_length);
- OPENSSL_strlcat(*data, pathsep, calculated_length);
- OPENSSL_strlcat(*data, name, calculated_length);
- }
- return 1;
-}
-
-static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
-{
- const char *p = NULL;
- size_t len = strlen(ctx->_.dir.search_name);
-
- /* If there are no search criteria, all names are accepted */
- if (ctx->_.dir.search_name[0] == '\0')
- return 1;
-
- /* If the expected type isn't supported, no name is accepted */
- if (ctx->expected_type != 0
- && ctx->expected_type != OSSL_STORE_INFO_CERT
- && ctx->expected_type != OSSL_STORE_INFO_CRL)
- return 0;
-
- /*
- * First, check the basename
- */
- if (OPENSSL_strncasecmp(name, ctx->_.dir.search_name, len) != 0
- || name[len] != '.')
- return 0;
- p = &name[len + 1];
-
- /*
- * Then, if the expected type is a CRL, check that the extension starts
- * with 'r'
- */
- if (*p == 'r') {
- p++;
- if (ctx->expected_type != 0
- && ctx->expected_type != OSSL_STORE_INFO_CRL)
- return 0;
- } else if (ctx->expected_type == OSSL_STORE_INFO_CRL) {
- return 0;
- }
-
- /*
- * Last, check that the rest of the extension is a decimal number, at
- * least one digit long.
- */
- if (!isdigit((unsigned char)*p))
- return 0;
- while (isdigit((unsigned char)*p))
- p++;
-
-#ifdef __VMS
- /*
- * One extra step here, check for a possible generation number.
- */
- if (*p == ';')
- for (p++; *p != '\0'; p++)
- if (!ossl_isdigit(*p))
- break;
-#endif
-
- /*
- * If we've reached the end of the string at this point, we've successfully
- * found a fitting file name.
- */
- return *p == '\0';
-}
-
-static int file_eof(OSSL_STORE_LOADER_CTX *ctx);
-static int file_error(OSSL_STORE_LOADER_CTX *ctx);
-static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_INFO *result = NULL;
-
- ctx->errcnt = 0;
-
- if (ctx->type == is_dir) {
- do {
- char *newname = NULL;
-
- if (ctx->_.dir.last_entry == NULL) {
- if (!ctx->_.dir.end_reached) {
- assert(ctx->_.dir.last_errno != 0);
- ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
- ctx->errcnt++;
- }
- return NULL;
- }
-
- if (ctx->_.dir.last_entry[0] != '.'
- && file_name_check(ctx, ctx->_.dir.last_entry)
- && !file_name_to_uri(ctx, ctx->_.dir.last_entry, &newname))
- return NULL;
-
- /*
- * On the first call (with a NULL context), OPENSSL_DIR_read()
- * cares about the second argument. On the following calls, it
- * only cares that it isn't NULL. Therefore, we can safely give
- * it our URI here.
- */
- ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, ctx->uri);
- ctx->_.dir.last_errno = errno;
- if (ctx->_.dir.last_entry == NULL && ctx->_.dir.last_errno == 0)
- ctx->_.dir.end_reached = 1;
-
- if (newname != NULL
- && (result = OSSL_STORE_INFO_new_NAME(newname)) == NULL) {
- OPENSSL_free(newname);
- ATTICerr(0, ERR_R_OSSL_STORE_LIB);
- return NULL;
- }
- } while (result == NULL && !file_eof(ctx));
- } else {
- int matchcount = -1;
-
- again:
- result = file_load_try_repeat(ctx, ui_method, ui_data);
- if (result != NULL)
- return result;
-
- if (file_eof(ctx))
- return NULL;
-
- do {
- char *pem_name = NULL; /* PEM record name */
- char *pem_header = NULL; /* PEM record header */
- unsigned char *data = NULL; /* DER encoded data */
- long len = 0; /* DER encoded data length */
-
- matchcount = -1;
- if (ctx->type == is_pem) {
- if (!file_read_pem(ctx->_.file.file, &pem_name, &pem_header,
- &data, &len, ui_method, ui_data, ctx->uri,
- (ctx->flags & FILE_FLAG_SECMEM) != 0)) {
- ctx->errcnt++;
- goto endloop;
- }
- } else {
- if ((result = file_try_read_msblob(ctx->_.file.file,
- &matchcount)) != NULL
- || (result = file_try_read_PVK(ctx->_.file.file,
- ui_method, ui_data, ctx->uri,
- &matchcount)) != NULL)
- goto endloop;
-
- if (!file_read_asn1(ctx->_.file.file, &data, &len)) {
- ctx->errcnt++;
- goto endloop;
- }
- }
-
- result = file_load_try_decode(ctx, pem_name, pem_header, data, len,
- ui_method, ui_data, &matchcount);
-
- if (result != NULL)
- goto endloop;
-
- /*
- * If a PEM name matches more than one handler, the handlers are
- * badly coded.
- */
- if (!ossl_assert(pem_name == NULL || matchcount <= 1)) {
- ctx->errcnt++;
- goto endloop;
- }
-
- if (matchcount > 1) {
- ATTICerr(0, ATTIC_R_AMBIGUOUS_CONTENT_TYPE);
- } else if (matchcount == 1) {
- /*
- * If there are other errors on the stack, they already show
- * what the problem is.
- */
- if (ERR_peek_error() == 0) {
- ATTICerr(0, ATTIC_R_UNSUPPORTED_CONTENT_TYPE);
- if (pem_name != NULL)
- ERR_add_error_data(3, "PEM type is '", pem_name, "'");
- }
- }
- if (matchcount > 0)
- ctx->errcnt++;
-
- endloop:
- pem_free_flag(pem_name, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0);
- pem_free_flag(pem_header, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0);
- pem_free_flag(data, (ctx->flags & FILE_FLAG_SECMEM) != 0, len);
- } while (matchcount == 0 && !file_eof(ctx) && !file_error(ctx));
-
- /* We bail out on ambiguity */
- if (matchcount > 1) {
- store_info_free(result);
- return NULL;
- }
-
- if (result != NULL
- && ctx->expected_type != 0
- && ctx->expected_type != OSSL_STORE_INFO_get_type(result)) {
- store_info_free(result);
- goto again;
- }
- }
-
- return result;
-}
-
-static int file_error(OSSL_STORE_LOADER_CTX *ctx)
-{
- return ctx->errcnt > 0;
-}
-
-static int file_eof(OSSL_STORE_LOADER_CTX *ctx)
-{
- if (ctx->type == is_dir)
- return ctx->_.dir.end_reached;
-
- if (ctx->_.file.last_handler != NULL
- && !ctx->_.file.last_handler->eof(ctx->_.file.last_handler_ctx))
- return 0;
- return BIO_eof(ctx->_.file.file);
-}
-
-static int file_close(OSSL_STORE_LOADER_CTX *ctx)
-{
- if ((ctx->flags & FILE_FLAG_ATTACHED) == 0) {
- if (ctx->type == is_dir)
- OPENSSL_DIR_end(&ctx->_.dir.ctx);
- else
- BIO_free_all(ctx->_.file.file);
- } else {
- /*
- * Because file_attach() called file_find_type(), we know that a
- * BIO_f_buffer() has been pushed on top of the regular BIO.
- */
- BIO *buff = ctx->_.file.file;
-
- /* Detach buff */
- (void)BIO_pop(ctx->_.file.file);
- /* Safety measure */
- ctx->_.file.file = NULL;
-
- BIO_free(buff);
- }
- OSSL_STORE_LOADER_CTX_free(ctx);
- return 1;
-}
-
-/*-
- * ENGINE management
- */
-
-static const char *loader_attic_id = "loader_attic";
-static const char *loader_attic_name = "'file:' loader";
-
-static OSSL_STORE_LOADER *loader_attic = NULL;
-
-static int loader_attic_init(ENGINE *e)
-{
- return 1;
-}
-
-
-static int loader_attic_finish(ENGINE *e)
-{
- return 1;
-}
-
-
-static int loader_attic_destroy(ENGINE *e)
-{
- OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader("file");
-
- if (loader == NULL)
- return 0;
-
- ERR_unload_ATTIC_strings();
- OSSL_STORE_LOADER_free(loader);
- return 1;
-}
-
-static int bind_loader_attic(ENGINE *e)
-{
-
- /* Ensure the ATTIC error handling is set up on best effort basis */
- ERR_load_ATTIC_strings();
-
- if (/* Create the OSSL_STORE_LOADER */
- (loader_attic = OSSL_STORE_LOADER_new(e, "file")) == NULL
- || !OSSL_STORE_LOADER_set_open_ex(loader_attic, file_open_ex)
- || !OSSL_STORE_LOADER_set_open(loader_attic, file_open)
- || !OSSL_STORE_LOADER_set_attach(loader_attic, file_attach)
- || !OSSL_STORE_LOADER_set_ctrl(loader_attic, file_ctrl)
- || !OSSL_STORE_LOADER_set_expect(loader_attic, file_expect)
- || !OSSL_STORE_LOADER_set_find(loader_attic, file_find)
- || !OSSL_STORE_LOADER_set_load(loader_attic, file_load)
- || !OSSL_STORE_LOADER_set_eof(loader_attic, file_eof)
- || !OSSL_STORE_LOADER_set_error(loader_attic, file_error)
- || !OSSL_STORE_LOADER_set_close(loader_attic, file_close)
- /* Init the engine itself */
- || !ENGINE_set_id(e, loader_attic_id)
- || !ENGINE_set_name(e, loader_attic_name)
- || !ENGINE_set_destroy_function(e, loader_attic_destroy)
- || !ENGINE_set_init_function(e, loader_attic_init)
- || !ENGINE_set_finish_function(e, loader_attic_finish)
- /* Finally, register the method with libcrypto */
- || !OSSL_STORE_register_loader(loader_attic)) {
- OSSL_STORE_LOADER_free(loader_attic);
- loader_attic = NULL;
- ATTICerr(0, ATTIC_R_INIT_FAILED);
- return 0;
- }
-
- return 1;
-}
-
-#ifdef OPENSSL_NO_DYNAMIC_ENGINE
-# error "Only allowed as dynamically shared object"
-#endif
-
-static int bind_helper(ENGINE *e, const char *id)
-{
- if (id && (strcmp(id, loader_attic_id) != 0))
- return 0;
- if (!bind_loader_attic(e))
- return 0;
- return 1;
-}
-
-IMPLEMENT_DYNAMIC_CHECK_FN()
- IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
+++ /dev/null
-# 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
+++ /dev/null
-# 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
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-# The INPUT HEADER is scanned for declarations
-# LIBNAME INPUT HEADER ERROR-TABLE FILE
-L OSSLTEST e_ossltest_err.h e_ossltest_err.c
+++ /dev/null
-# 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
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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 */