aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/cloud/aws-import64
-rwxr-xr-xcontrib/crypto/cmsdetach80
-rw-r--r--contrib/rom-o-matic/README62
-rw-r--r--contrib/rom-o-matic/bottom.php62
-rw-r--r--contrib/rom-o-matic/build.php311
-rw-r--r--contrib/rom-o-matic/customize-flags.php69
-rw-r--r--contrib/rom-o-matic/directions.php63
-rw-r--r--contrib/rom-o-matic/doc/AUTOBOOT_CMD.html1
-rw-r--r--contrib/rom-o-matic/doc/BANNER_TIMEOUT.html1
-rw-r--r--contrib/rom-o-matic/doc/COMCONSOLE.html3
-rw-r--r--contrib/rom-o-matic/doc/COMDATA.html1
-rw-r--r--contrib/rom-o-matic/doc/COMPARITY.html1
-rw-r--r--contrib/rom-o-matic/doc/COMPRESERVE.html1
-rw-r--r--contrib/rom-o-matic/doc/COMSPEED.html1
-rw-r--r--contrib/rom-o-matic/doc/COMSTOP.html1
-rw-r--r--contrib/rom-o-matic/doc/CONFIG_CMD.html1
-rw-r--r--contrib/rom-o-matic/doc/CONSOLE_PC_BIOS.html1
-rw-r--r--contrib/rom-o-matic/doc/CONSOLE_SERIAL.html1
-rw-r--r--contrib/rom-o-matic/doc/CRYPTO_80211_WEP.html1
-rw-r--r--contrib/rom-o-matic/doc/CRYPTO_80211_WPA.html1
-rw-r--r--contrib/rom-o-matic/doc/CRYPTO_80211_WPA2.html1
-rw-r--r--contrib/rom-o-matic/doc/DHCP_CMD.html1
-rw-r--r--contrib/rom-o-matic/doc/DNS_RESOLVER.html1
-rw-r--r--contrib/rom-o-matic/doc/DOWNLOAD_PROTO_FTP.html1
-rw-r--r--contrib/rom-o-matic/doc/DOWNLOAD_PROTO_HTTP.html1
-rw-r--r--contrib/rom-o-matic/doc/DOWNLOAD_PROTO_TFTP.html1
-rw-r--r--contrib/rom-o-matic/doc/IFMGMT_CMD.html1
-rw-r--r--contrib/rom-o-matic/doc/IMAGE_BZIMAGE.html1
-rw-r--r--contrib/rom-o-matic/doc/IMAGE_CMD.html1
-rw-r--r--contrib/rom-o-matic/doc/IMAGE_ELF.html1
-rw-r--r--contrib/rom-o-matic/doc/IMAGE_MULTIBOOT.html1
-rw-r--r--contrib/rom-o-matic/doc/IMAGE_NBI.html1
-rw-r--r--contrib/rom-o-matic/doc/IMAGE_PXE.html1
-rw-r--r--contrib/rom-o-matic/doc/IMAGE_SCRIPT.html1
-rw-r--r--contrib/rom-o-matic/doc/IWMGMT_CMD.html1
-rw-r--r--contrib/rom-o-matic/doc/NMB_RESOLVER.html1
-rw-r--r--contrib/rom-o-matic/doc/NVO_CMD.html1
-rw-r--r--contrib/rom-o-matic/doc/ROUTE_CMD.html1
-rw-r--r--contrib/rom-o-matic/doc/SANBOOT_CMD.html1
-rw-r--r--contrib/rom-o-matic/flag-table.php531
-rw-r--r--contrib/rom-o-matic/globals.php51
-rw-r--r--contrib/rom-o-matic/index.php47
-rw-r--r--contrib/rom-o-matic/top.php41
-rw-r--r--contrib/rom-o-matic/utils.php684
-rw-r--r--src/Makefile1
-rw-r--r--src/Makefile.housekeeping5
-rw-r--r--src/arch/arm/Makefile4
-rw-r--r--src/arch/arm/include/bits/acpi.h12
-rw-r--r--src/arch/arm/include/bits/hyperv.h12
-rw-r--r--src/arch/arm/include/bits/iomap.h12
-rw-r--r--src/arch/arm/include/bits/mp.h12
-rw-r--r--src/arch/arm/include/bits/pci_io.h12
-rw-r--r--src/arch/arm/include/bits/reboot.h12
-rw-r--r--src/arch/arm/include/bits/sanboot.h12
-rw-r--r--src/arch/arm/include/bits/smbios.h12
-rw-r--r--src/arch/arm/include/bits/time.h12
-rw-r--r--src/arch/arm/include/bits/uaccess.h12
-rw-r--r--src/arch/arm/include/bits/uart.h12
-rw-r--r--src/arch/arm/include/bits/umalloc.h12
-rw-r--r--src/arch/arm32/include/bits/tcpip.h19
-rw-r--r--src/arch/arm32/include/gdbmach.h45
-rw-r--r--src/arch/arm64/include/gdbmach.h45
-rw-r--r--src/arch/i386/include/bits/gdbmach.h (renamed from src/arch/i386/include/gdbmach.h)0
-rw-r--r--src/arch/loong64/Makefile3
-rw-r--r--src/arch/loong64/include/bits/acpi.h12
-rw-r--r--src/arch/loong64/include/bits/hyperv.h12
-rw-r--r--src/arch/loong64/include/bits/iomap.h12
-rw-r--r--src/arch/loong64/include/bits/mp.h12
-rw-r--r--src/arch/loong64/include/bits/pci_io.h12
-rw-r--r--src/arch/loong64/include/bits/reboot.h12
-rw-r--r--src/arch/loong64/include/bits/sanboot.h12
-rw-r--r--src/arch/loong64/include/bits/smbios.h12
-rw-r--r--src/arch/loong64/include/bits/tcpip.h19
-rw-r--r--src/arch/loong64/include/bits/time.h12
-rw-r--r--src/arch/loong64/include/bits/uaccess.h12
-rw-r--r--src/arch/loong64/include/bits/uart.h12
-rw-r--r--src/arch/loong64/include/bits/umalloc.h12
-rw-r--r--src/arch/x86/Makefile4
-rw-r--r--src/arch/x86/core/cpuid_settings.c18
-rw-r--r--src/arch/x86/core/gdbmach.c1
-rw-r--r--src/arch/x86/core/pcidirect.c1
-rw-r--r--src/arch/x86/include/ipxe/pcibios.h10
-rw-r--r--src/arch/x86/include/ipxe/pcicloud.h10
-rw-r--r--src/arch/x86/include/ipxe/pcidirect.h10
-rw-r--r--src/arch/x86/interface/pcbios/pcibios.c1
-rw-r--r--src/arch/x86/interface/pcbios/pcicloud.c1
-rw-r--r--src/arch/x86_64/include/bits/gdbmach.h (renamed from src/arch/x86_64/include/gdbmach.h)0
-rw-r--r--src/config/config.c3
-rw-r--r--src/config/config_crypto.c10
-rw-r--r--src/config/general.h1
-rw-r--r--src/core/archive.c7
-rw-r--r--src/core/gdbstub.c1
-rw-r--r--src/core/image.c19
-rw-r--r--src/crypto/asn1.c178
-rw-r--r--src/crypto/certstore.c62
-rw-r--r--src/crypto/cms.c1080
-rw-r--r--src/crypto/crypto_null.c24
-rw-r--r--src/crypto/mishmash/oid_aes_cbc.c60
-rw-r--r--src/crypto/mishmash/oid_aes_gcm.c60
-rw-r--r--src/crypto/ocsp.c21
-rw-r--r--src/crypto/rsa.c323
-rw-r--r--src/crypto/x509.c150
-rw-r--r--src/drivers/bus/ecam.c1
-rw-r--r--src/drivers/bus/pci.c4
-rw-r--r--src/drivers/net/ena.c7
-rw-r--r--src/drivers/net/ena.h15
-rw-r--r--src/drivers/net/etherfabric.c15
-rw-r--r--src/drivers/net/gve.c9
-rw-r--r--src/drivers/net/iphone.c19
-rw-r--r--src/drivers/net/marvell/aqc1xx.c629
-rw-r--r--src/drivers/net/marvell/aqc1xx.h270
-rw-r--r--src/drivers/net/marvell/atl2_hw.c225
-rw-r--r--src/drivers/net/marvell/atl2_hw.h94
-rw-r--r--src/drivers/net/marvell/atl_hw.c313
-rw-r--r--src/drivers/net/marvell/atl_hw.h83
-rw-r--r--src/hci/commands/image_crypt_cmd.c124
-rw-r--r--src/image/der.c15
-rw-r--r--src/include/bits/acpi.h15
-rw-r--r--src/include/bits/gdbmach.h (renamed from src/arch/loong64/include/gdbmach.h)12
-rw-r--r--src/include/bits/hyperv.h15
-rw-r--r--src/include/bits/iomap.h15
-rw-r--r--src/include/bits/mp.h15
-rw-r--r--src/include/bits/nap.h15
-rw-r--r--src/include/bits/pci_io.h15
-rw-r--r--src/include/bits/reboot.h15
-rw-r--r--src/include/bits/sanboot.h15
-rw-r--r--src/include/bits/smbios.h15
-rw-r--r--src/include/bits/tcpip.h32
-rw-r--r--src/include/bits/time.h15
-rw-r--r--src/include/bits/uaccess.h15
-rw-r--r--src/include/bits/uart.h15
-rw-r--r--src/include/bits/umalloc.h15
-rw-r--r--src/include/bits/xen.h (renamed from src/arch/loong64/include/bits/xen.h)5
-rw-r--r--src/include/ipxe/asn1.h82
-rw-r--r--src/include/ipxe/certstore.h4
-rw-r--r--src/include/ipxe/cms.h111
-rw-r--r--src/include/ipxe/crypto.h111
-rw-r--r--src/include/ipxe/ecam.h10
-rw-r--r--src/include/ipxe/efi/efi_pci_api.h14
-rw-r--r--src/include/ipxe/errfile.h3
-rw-r--r--src/include/ipxe/gdbstub.h2
-rw-r--r--src/include/ipxe/image.h1
-rw-r--r--src/include/ipxe/linux/linux_pci.h10
-rw-r--r--src/include/ipxe/pci_io.h7
-rw-r--r--src/include/ipxe/rsa.h25
-rw-r--r--src/include/ipxe/tls.h135
-rw-r--r--src/include/ipxe/x509.h21
-rw-r--r--src/include/usr/imgcrypt.h17
-rw-r--r--src/interface/efi/efi_pci.c241
-rw-r--r--src/interface/linux/linux_pci.c1
-rw-r--r--src/net/tls.c415
-rw-r--r--src/net/validator.c6
-rw-r--r--src/tests/cms_test.c518
-rw-r--r--src/tests/pubkey_test.c131
-rw-r--r--src/tests/pubkey_test.h278
-rw-r--r--src/tests/rsa_test.c195
-rw-r--r--src/usr/imgcrypt.c75
-rw-r--r--src/usr/imgtrust.c42
158 files changed, 5195 insertions, 3910 deletions
diff --git a/contrib/cloud/aws-import b/contrib/cloud/aws-import
index ace0058..3b6b522 100755
--- a/contrib/cloud/aws-import
+++ b/contrib/cloud/aws-import
@@ -22,11 +22,12 @@ def detect_architecture(image):
return 'x86_64'
-def create_snapshot(region, description, image):
+def create_snapshot(region, description, image, tags):
"""Create an EBS snapshot"""
client = boto3.client('ebs', region_name=region)
snapshot = client.start_snapshot(VolumeSize=1,
- Description=description)
+ Description=description,
+ Tags=tags)
snapshot_id = snapshot['SnapshotId']
with open(image, 'rb') as fh:
for block in count():
@@ -46,21 +47,42 @@ def create_snapshot(region, description, image):
return snapshot_id
-def import_image(region, name, architecture, image, public, overwrite):
- """Import an AMI image"""
+def delete_images(region, filters, retain):
client = boto3.client('ec2', region_name=region)
resource = boto3.resource('ec2', region_name=region)
- description = '%s (%s)' % (name, architecture)
- images = client.describe_images(Filters=[{'Name': 'name',
- 'Values': [description]}])
- if overwrite and images['Images']:
- images = images['Images'][0]
- image_id = images['ImageId']
- snapshot_id = images['BlockDeviceMappings'][0]['Ebs']['SnapshotId']
+ images = client.describe_images(Owners=['self'], Filters=filters)
+ old_images = sorted(images['Images'], key=lambda x: x['CreationDate'])
+ if retain > 0:
+ old_images = old_images[:-retain]
+ for image in old_images:
+ image_id = image['ImageId']
+ snapshot_id = image['BlockDeviceMappings'][0]['Ebs']['SnapshotId']
resource.Image(image_id).deregister()
resource.Snapshot(snapshot_id).delete()
+
+
+def import_image(region, name, family, architecture, image, public, overwrite,
+ retain):
+ """Import an AMI image"""
+ client = boto3.client('ec2', region_name=region)
+ resource = boto3.resource('ec2', region_name=region)
+ description = '%s (%s)' % (name, architecture)
+ tags = [
+ {'Key': 'family', 'Value': family},
+ {'Key': 'architecture', 'Value': architecture},
+ ]
+ if overwrite:
+ filters = [{'Name': 'name', 'Values': [description]}]
+ delete_images(region=region, filters=filters, retain=0)
+ if retain is not None:
+ filters = [
+ {'Name': 'tag:family', 'Values': [family]},
+ {'Name': 'tag:architecture', 'Values': [architecture]},
+ {'Name': 'is-public', 'Values': [str(public).lower()]},
+ ]
+ delete_images(region=region, filters=filters, retain=retain)
snapshot_id = create_snapshot(region=region, description=description,
- image=image)
+ image=image, tags=tags)
client.get_waiter('snapshot_completed').wait(SnapshotIds=[snapshot_id])
image = client.register_image(Architecture=architecture,
BlockDeviceMappings=[{
@@ -72,6 +94,10 @@ def import_image(region, name, architecture, image, public, overwrite):
}],
EnaSupport=True,
Name=description,
+ TagSpecifications=[{
+ 'ResourceType': 'image',
+ 'Tags': tags,
+ }],
RootDeviceName='/dev/sda1',
SriovNetSupport='simple',
VirtualizationType='hvm')
@@ -94,10 +120,14 @@ def launch_link(region, image_id):
parser = argparse.ArgumentParser(description="Import AWS EC2 image (AMI)")
parser.add_argument('--name', '-n',
help="Image name")
+parser.add_argument('--family', '-f',
+ help="Image family name")
parser.add_argument('--public', '-p', action='store_true',
help="Make image public")
parser.add_argument('--overwrite', action='store_true',
help="Overwrite any existing image with same name")
+parser.add_argument('--retain', type=int, metavar='NUM',
+ help="Retain at most <NUM> old images")
parser.add_argument('--region', '-r', action='append',
help="AWS region(s)")
parser.add_argument('--wiki', '-w', metavar='FILE',
@@ -108,9 +138,13 @@ args = parser.parse_args()
# Detect CPU architectures
architectures = {image: detect_architecture(image) for image in args.image}
+# Use default family name if none specified
+if not args.family:
+ args.family = 'iPXE'
+
# Use default name if none specified
if not args.name:
- args.name = 'iPXE (%s)' % date.today().strftime('%Y-%m-%d')
+ args.name = '%s (%s)' % (args.family, date.today().strftime('%Y-%m-%d'))
# Use all regions if none specified
if not args.region:
@@ -123,10 +157,12 @@ with ThreadPoolExecutor(max_workers=len(imports)) as executor:
futures = {executor.submit(import_image,
region=region,
name=args.name,
+ family=args.family,
architecture=architectures[image],
image=image,
public=args.public,
- overwrite=args.overwrite): (region, image)
+ overwrite=args.overwrite,
+ retain=args.retain): (region, image)
for region, image in imports}
results = {futures[future]: future.result()
for future in as_completed(futures)}
diff --git a/contrib/crypto/cmsdetach b/contrib/crypto/cmsdetach
new file mode 100755
index 0000000..0075009
--- /dev/null
+++ b/contrib/crypto/cmsdetach
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+
+"""Detach CMS encrypted data.
+
+Detach encrypted data from a CMS envelopedData or authEnvelopedData
+message into a separate file.
+"""
+
+import argparse
+
+import asn1
+
+# Parse command-line arguments
+#
+parser = argparse.ArgumentParser(
+ description=__doc__,
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+)
+parser.add_argument("-d", "--data", metavar="FILE",
+ help="Write detached data (without envelope) to FILE")
+parser.add_argument("-e", "--envelope", metavar="FILE",
+ help="Write envelope (without data) to FILE")
+parser.add_argument("-o", "--overwrite", action="store_true",
+ help="Overwrite output files")
+parser.add_argument("file", help="Input envelope file")
+args = parser.parse_args()
+if args.data is None and args.envelope is None:
+ parser.error("at least one of --data and --envelope is required")
+outmode = "wb" if args.overwrite else "xb"
+
+# Create decoder
+#
+decoder = asn1.Decoder()
+with open(args.file, mode="rb") as fh:
+ decoder.start(fh.read())
+
+# Create encoder
+#
+encoder = asn1.Encoder()
+encoder.start()
+
+# Detach encrypted data
+#
+data = None
+datastack = [
+ asn1.Numbers.Sequence, 0, asn1.Numbers.Sequence, asn1.Numbers.Sequence
+]
+stack = []
+while stack or not decoder.eof():
+ if decoder.eof():
+ encoder.leave()
+ decoder.leave()
+ stack.pop()
+ else:
+ tag = decoder.peek()
+ if tag.typ == asn1.Types.Constructed:
+ encoder.enter(nr=tag.nr, cls=tag.cls)
+ decoder.enter()
+ stack.append(tag.nr)
+ else:
+ (tag, value) = decoder.read()
+ if stack == datastack and tag.nr == 0:
+ data = value
+ else:
+ encoder.write(value, nr=tag.nr, cls=tag.cls)
+envelope = encoder.output()
+if data is None:
+ parser.error("Input file does not contain any encrypted data")
+
+# Write envelope (without data), if applicable
+#
+if args.envelope:
+ with open(args.envelope, mode=outmode) as fh:
+ fh.write(envelope)
+
+# Write data (without envelope), if applicable
+#
+if args.data:
+ with open(args.data, mode=outmode) as fh:
+ fh.write(data)
diff --git a/contrib/rom-o-matic/README b/contrib/rom-o-matic/README
deleted file mode 100644
index b68cf77..0000000
--- a/contrib/rom-o-matic/README
+++ /dev/null
@@ -1,62 +0,0 @@
-ROM-o-matic web interface for building iPXE ROMs
-------------------------------------------------
-
-This web application generates iPXE images and sends them to a web
-browser.
-
-Available as part of the iPXE source code distribution, which can be
-downlaoded from http://etherboot.org/
-
-Author: Marty Connor <mdc@etherboot.org>
-License: GPLv2
-Support: http://etherboot.org/mailman/listinfo/ipxe
- Please send support questions to the iPXE mailing list
-
-System Requirements
--------------------
-- Apache web server
-- PHP 4+
-- Tools required to build iPXE installed on the server
- - gcc, mtools, syslinux, perl, etc.
-
-Setup
------
-As distributed, it is expected that the rom-o-matic source code
-directory is in the contrib directory of a iPXE source distribution.
-
-The easiest way to do this is to simply put a iPXE source distribution
-in a web server accessible directory.
-
-If this is not the case, you will need to either edit the file
-
- "globals.php"
-
-or create a file called
-
- "local-config.php"
-
-containing the following lines:
-
-<?php
-$src_dir = "../../src";
-?>
-
-Then change the line beginning "$src_dir = " to the path of your iPXE
-source code tree.
-
-To make build times shorter, before you run rom-o-matic for the first time
-you should cd to the ipxe "src" directory and enter the following
-commands:
-
- $ make
- $ make bin/NIC
-
-This will pro-compile most object files and will make your rom-o-matic
-builds much faster.
-
-Running rom-o-matic from a web browser
---------------------------------------
-Enter a URL like:
-
- http://example.com/ipxe-1.x.x/contrib/rom-o-matic
-
diff --git a/contrib/rom-o-matic/bottom.php b/contrib/rom-o-matic/bottom.php
deleted file mode 100644
index 9ba8e31..0000000
--- a/contrib/rom-o-matic/bottom.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-/**
- * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
- * Copyright (C) 2009 Entity Cyber, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-?>
-<hr>
-<h4>
-Resources:
-</h4>
-<ul>
- <li>
- Source code for iPXE images is available at
- <a href="http://www.ipxe.org/download" target="_blank">
- http://www.ipxe.org/download</a>
- <br><br>
- </li>
- <li>
- For general information about using iPXE, please visit the
- <a href="http://www.ipxe.org/" target="_blank">
- iPXE Project Home Page</a>
- <br><br>
- </li>
- <li>
- For Email-based support for iPXE please join
- <a href="http://www.ipxe.org/contact" target="_blank">
- iPXE Project mailing lists.</a>
- <br><br>
- </li>
- <li>
- For real-time online iPXE support via IRC please visit the
- <a href="irc://irc.freenode.net/%23ipxe"> #ipxe channel
- of irc.freenode.net</a>.
- <br><br>
- </li>
-</ul>
-<hr>
- <font size="-1">
- <br>
- Please email <a href="mailto:<?php echo "${webmaster_email}" ?>"><?php echo "${webmaster_email}"?></a>
- with questions or comments about this website.
- </font>
- <br><br>
-<hr>
-</body>
-</html>
diff --git a/contrib/rom-o-matic/build.php b/contrib/rom-o-matic/build.php
deleted file mode 100644
index b2b5bb4..0000000
--- a/contrib/rom-o-matic/build.php
+++ /dev/null
@@ -1,311 +0,0 @@
-<?php // -*- Mode: PHP; -*-
-
-/**
- * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
- * Copyright (C) 2009 Entity Cyber, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-// Get utility functions and set globals
-require_once "utils.php";
-
-// Make sure at least $A (action) was supplied
-if ( ! isset ( $_POST['A'] ) ) {
-
- // Present user with form to customize build options
- require_once "customize-flags.php";
-
- exit ();
-
-// If user chose "Customize" option on form
-} else if ( $_POST['A'] == "Customize" ) {
-
- // Present user with form to customize build options
- require_once "customize-flags.php";
-
- exit ();
-
-// The following conditional includes all other cases except "Get Image"
-// particularly the explicit ($A == "Start Over") case
-} else if ( $_POST['A'] != "Get Image" ) {
-
- // Note that this method of redirections discards all the
- // configuration flags, which is intentional in this case.
-
- $dest = curDirURL ();
- header ( "Location: $dest" );
-
- // This next "echo" should normally not be seen, because
- // the "header" statement above should cause immediate
- // redirection but just in case...
-
- echo "Try this link: <a href=\"$dest\">$dest</a>";
-
- exit ();
-}
-
-// OK, we're going to try to use whatever options have been set
-// to build an image.
-
-// Make sure at least $nic was supplied
-if ( ! isset ( $_POST['nic'] ) ) {
- die ( "No NIC supplied!" );
-}
-if ( isset ( $nics[$_POST['nic']] ) ) {
- $nic = $nics[$_POST['nic']];
-} else {
- die ( "Invalid NIC \"${_POST['nic']}\" supplied!" );
-}
-
-// Fetch flags
-$flags = get_flags ();
-
-// Get requested format
-$ofmt = isset ( $_POST['ofmt'] ) ? $_POST['ofmt'] : "";
-$fmt_extension = isset ( $ofmts[$ofmt] ) ? $ofmts[$ofmt] : 'dsk';
-
-// Handle some special cases
-
-$pci_vendor_code = "";
-$pci_device_code = "";
-
-if ( $nic == 'undionly' && $fmt_extension == "pxe" ) {
-
- // undionly.pxe can't work because it unloads the PXE stack
- // that it needs to communicate with, so we set the extension
- // to .kpxe, which has a chance of working. The extension
- // .kkpxe is another option.
-
- $fmt_extension = "kpxe";
-
-} else if ( $fmt_extension == "rom" ) {
-
- if ( ! isset ( $_POST['pci_vendor_code'] )
- || ! isset ( $_POST['pci_device_code'] ) ) {
- die ( "rom output format selected but PCI code(s) missing!" );
- }
-
- $pci_vendor_code = $_POST['pci_vendor_code'];
- $pci_device_code = $_POST['pci_device_code'];
-
- if ( $pci_vendor_code == ""
- || $pci_device_code == "" ) {
- die ( "rom output format selected but PCI code(s) missing!" );
- }
-
- // Try to be forgiving of 0xAAAA format
- if ( strtolower ( substr ( $pci_vendor_code, 0, 2 ) ) == "0x"
- && strlen ( $pci_vendor_code ) == 6 ) {
- $pci_vendor_code = substr ( $pci_vendor_code, 2, 4 );
- }
- if ( strtolower ( substr ( $pci_device_code, 0, 2 ) ) == "0x"
- && strlen ( $pci_device_code ) == 6 ) {
- $pci_device_code = substr ( $pci_device_code, 2, 4 );
- }
-
- // concatenate the pci codes to get the $nic part of the
- // Make target
- $pci_codes = strtolower ( $pci_vendor_code . $pci_device_code );
-
- $nic = $pci_codes;
- if ( ! isset ( $roms[$pci_codes] ) ) {
- die ( "Sorry, no network driver supports PCI codes<br>"
- . "${_POST['pci_vendor_code']}:"
- . "${_POST['pci_device_code']}" );
- }
-} else if ( $fmt_extension != "rom"
- && ( $pci_vendor_code != "" || $pci_device_code != "" ) ) {
- die ( "'$fmt_extension' format was selected but PCI IDs were"
- . " also entered.<br>Did you mean to select 'rom' output format"
- . " instead?" );
-}
-
-/**
- * remove temporary build directory
- *
- * @return bool true if removal is successful, false otherwise
- */
-function rm_build_dir ()
-{
- global $build_dir;
- global $keep_build_dir;
-
- if ( $keep_build_dir !== true ) {
- rm_file_or_dir ( $build_dir );
- }
-}
-
-// Arrange for the build directory to always be removed on exit.
-$build_dir = "";
-$keep_build_dir = false;
-register_shutdown_function ( 'rm_build_dir' );
-
-// Make temporary copy of src directory
-$build_dir = mktempcopy ( "$src_dir", "/tmp", "MDCROM" );
-$config_dir = $build_dir . "/config";
-
-// Write config files with supplied flags
-write_ipxe_config_files ( $config_dir, $flags );
-
-// Handle a possible embedded script
-$emb_script_cmd = "";
-$embedded_script = isset ( $_POST['embedded_script'] ) ? $_POST['embedded_script'] : "";
-if ( $embedded_script != "" ) {
- $emb_script_path = "$build_dir" . "/script0.ipxe";
-
- if ( substr ( $embedded_script, 0, 5 ) != "#!ipxe" ) {
- $embedded_script = "#!ipxe\n" . $embedded_script;
- }
-
- // iPXE 0.9.7 doesn't like '\r\n" in the shebang...
- $embedded_script = str_replace ( "\r\n", "\n", $embedded_script );
-
- write_file_from_string ( $emb_script_path, $embedded_script );
- $emb_script_cmd = "EMBEDDED_IMAGE=${emb_script_path}";
-}
-
-// Make the requested image. $status is set to 0 on success
-$make_target = "bin/${nic}.${fmt_extension}";
-$gitversion = exec('git describe --always --abbrev=1 --match "" 2>/dev/null');
-if ($gitversion) {
- $gitversion = "GITVERSION=$gitversion";
-}
-
-$make_cmd = "make -C '$build_dir' '$make_target' $gitversion $emb_script_cmd 2>&1";
-
-exec ( $make_cmd, $maketxt, $status );
-
-// Uncomment the following section for debugging
-
-/**
-
-echo "<h2>build.php:</h2>";
-echo "<h3>Begin debugging output</h3>";
-
-//echo "<h3>\$_POST variables</h3>";
-//echo "<pre>"; var_dump ( $_POST ); echo "</pre>";
-
-echo "<h3>Build options:</h3>";
-echo "<strong>Build directory is:</strong> $build_dir" . "<br><br>";
-echo "\$_POST['ofmt'] = " . "\"${_POST['ofmt']}\"" . "<br>";
-echo "\$_POST['nic'] = " . "\"${_POST['nic']}\"" . "<br>";
-echo "\$_POST['pci_vendor_code'] = " . "\"${_POST['pci_vendor_code']}\"" . "<br>";
-echo "\$_POST['pci_device_code'] = " . "\"${_POST['pci_device_code']}\"" . "<br>";
-
-echo "<h3>Flags:</h3>";
-show_flags ( $flags );
-
-if ( $embedded_script != "" ) {
- echo "<h3>Embedded script:</h3>";
- echo "<blockquote>"."<pre>";
- echo $embedded_script;
- echo "</pre>"."</blockquote>";
-}
-
-echo "<h3>Make output:</h3>";
-echo "Make command: " . $make_cmd . "<br>";
-echo "Build status = <? echo $status ?>" . "<br>";
-echo "<blockquote>"."<pre>";
-echo htmlentities ( implode ("\n", $maketxt ) );
-echo "</pre>"."</blockquote>";
-// Uncomment the next line if you want to keep the
-// build directory around for inspection after building.
-$keep_build_dir = true;
-die ( "<h3>End debugging output</h3>" );
-
-**/ // End debugging section
-
-// Send ROM to browser (with extreme prejudice)
-
-if ( $status == 0 ) {
-
- $fp = fopen("${build_dir}/${make_target}", "rb" );
- if ( $fp > 0 ) {
-
- $len = filesize ( "${build_dir}/${make_target}" );
- if ( $len > 0 ) {
-
- $buf = fread ( $fp, $len );
- fclose ( $fp );
-
- // Delete build directory as soon as it is not needed
- rm_build_dir ();
-
- $output_filename = preg_replace('/[^a-z0-9\+\.\-]/i', '', "ipxe-${version}-${nic}.${fmt_extension}");
-
- // Try to force IE to handle downloading right.
- Header ( "Cache-control: private");
- Header ( "Content-Type: application/x-octet-stream; " .
- "name=$output_filename");
- Header ( "Content-Disposition: attachment; " .
- "Filename=$output_filename");
- Header ( "Content-Location: $output_filename");
- Header ( "Content-Length: $len");
-
- echo $buf;
-
- exit ();
- }
- }
-}
-
-/*
- * If we reach this point, the build has failed, and we provide
- * debugging information for a potential bug report
- *
- */
-
-// Remove build directory
-rm_build_dir ();
-
-// Announce failure if $status from make was non-zero
-echo "<h2>Build failed. Status = " . $status . "</h2>";
-echo "<h2>build.php:</h2>";
-echo "<h3>Build options:</h3>";
-echo "<strong>Build directory is:</strong> $build_dir" . "<br><br>";
-echo "\$_POST['ofmt'] = " . "\"${_POST['ofmt']}\"" . "<br>";
-echo "\$_POST['nic'] = " . "\"${_POST['nic']}\"" . "<br>";
-echo "\$_POST['pci_vendor_code'] = " . "\"${_POST['pci_vendor_code']}\"" . "<br>";
-echo "\$_POST['pci_device_code'] = " . "\"${_POST['pci_device_code']}\"" . "<br>";
-
-echo "<h3>Flags:</h3>";
-show_flags ( $flags );
-
-if ( $embedded_script != "" ) {
- echo "<h3>Embedded script:</h3>";
- echo "<blockquote>"."<pre>";
- echo $embedded_script;
- echo "</pre>"."</blockquote>";
-}
-
-echo "<h3>Make output:</h3>";
-echo "Make command: " . $make_cmd . "<br>";
-echo "<blockquote>"."<pre>";
-echo htmlentities ( implode ("\n", $maketxt ) );
-echo "</pre>"."</blockquote>";
-
-echo "Please let us know that this happened, and paste the above output into your email message.<br>";
-
-include_once $bottom_inc;
-
-// For emacs:
-// Local variables:
-// c-basic-offset: 4
-// c-indent-level: 4
-// tab-width: 4
-// End:
-
-?>
diff --git a/contrib/rom-o-matic/customize-flags.php b/contrib/rom-o-matic/customize-flags.php
deleted file mode 100644
index e283921..0000000
--- a/contrib/rom-o-matic/customize-flags.php
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php // -*- Mode: PHP; -*-
-
-/**
- * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
- * Copyright (C) 2009 Entity Cyber, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-// Get utility functions and set globals
-require_once "utils.php";
-
-// Prepare settable compile options for presentation to user
-$flags = default_flags ();
-
-$build = "<input type=\"submit\" name=\"A\" value=\"Get Image\">";
-$restart = "<input type=\"submit\" name=\"A\" value=\"Start Over\">";
-
-// Begin html output
-include_once $top_inc;
-
-?>
-
-<form action="build.php" method=POST>
- <input type="hidden" name="version" value = "<?php echo $version ?>">
- <input type="hidden" name="use_flags" value="1">
- <h3>
- Make changes below and press <?php echo $build ?> to create an image, <br>
- Or press <?php echo $restart ?> to return to the main page.
- </h3>
- <hr>
- <ul>
- <?php require ( "directions.php" ); ?>
- </ul>
- <hr>
- <?php echo_flags( $flags ); ?>
- <hr>
- <h3>Embedded Script:</h3>
- <?php echo textarea ( "embedded_script", "", "10", "50" ); ?>
- <br><br>
- <hr>
- <center><table width="35%"><tr>
- <td align="left"> <?php echo $build; ?> </td>
- <td align="right"> <?php echo $restart ?></td>
- </tr></table></center>
-</form>
-
-<?php include_once $bottom_inc; ?>
-<?
-// For emacs:
-//
-// Local variables:
-// c-basic-offset: 4
-// c-indent-level: 4
-// tab-width: 4
-// End:
-?>
diff --git a/contrib/rom-o-matic/directions.php b/contrib/rom-o-matic/directions.php
deleted file mode 100644
index 540121e..0000000
--- a/contrib/rom-o-matic/directions.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-/**
- * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
- * Copyright (C) 2009 Entity Cyber, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-?>
- <li>
- Choose an output format: <?php echo keys_menubox ( "ofmt", $ofmts,
- isset ( $_POST['ofmt'] ) ? $_POST['ofmt'] : "") ?>
- <br><br>
- </li>
- <li>
- Choose a NIC type: <?php echo keys_menubox ( "nic", $nics,
- isset ( $_POST['nic'] ) ? $_POST['nic'] : "" ) ?>
- <br><br>
- </li>
- <li>
- <strong>( optional &mdash; for binary ROM image format only )</strong> <br><br>
- If you choose <em>Binary ROM image</em> as your output format, you must<br>
- enter <strong>4 hex digits</strong> below for
- <em>PCI VENDOR CODE</em> and <em>PCI DEVICE CODE</em> <br>
- that match the NIC device for which you are making this image.<br><br>
- Information on how to determine NIC PCI IDs may be found
- <a href="http://www.ipxe.org/howto/romburning"
- target="_blank">here</a>.
- <br><br>
- PCI VENDOR CODE: <?php echo textbox ( "pci_vendor_code",
- isset ( $_POST['pci_vendor_code'] ) ? $_POST['pci_vendor_code']
- : "", 6 ); ?>
- &nbsp;&nbsp;
- PCI DEVICE CODE: <?php echo textbox ( "pci_device_code",
- isset ( $_POST['pci_device_code'] ) ? $_POST['pci_device_code']
- : "", 6 ); ?>
- <h4>Please note for ROM images:</h4>
- <ul>
- <li>
- If you enter PCI IDs, we will attempt to determine the correct<br>
- driver to support them, and will ignore any NIC type entered
- above.<br><br>
- </li>
- <li>
- iPXE does not support all possible PCI IDs for supported
- NICs.
- <br><br>
- </li>
- </ul>
- </li>
diff --git a/contrib/rom-o-matic/doc/AUTOBOOT_CMD.html b/contrib/rom-o-matic/doc/AUTOBOOT_CMD.html
deleted file mode 100644
index 444c5e6..0000000
--- a/contrib/rom-o-matic/doc/AUTOBOOT_CMD.html
+++ /dev/null
@@ -1 +0,0 @@
-Automatic booting
diff --git a/contrib/rom-o-matic/doc/BANNER_TIMEOUT.html b/contrib/rom-o-matic/doc/BANNER_TIMEOUT.html
deleted file mode 100644
index e135897..0000000
--- a/contrib/rom-o-matic/doc/BANNER_TIMEOUT.html
+++ /dev/null
@@ -1 +0,0 @@
-Tenths of a second for which the shell banner should appear
diff --git a/contrib/rom-o-matic/doc/COMCONSOLE.html b/contrib/rom-o-matic/doc/COMCONSOLE.html
deleted file mode 100644
index e7036c0..0000000
--- a/contrib/rom-o-matic/doc/COMCONSOLE.html
+++ /dev/null
@@ -1,3 +0,0 @@
-Serial Console I/O port address. Common addresses are:<br>
-COM1 => 0x3f8, COM2 => 0x2f8, COM3 => 0x3e8, COM4 => 0x2e8
-
diff --git a/contrib/rom-o-matic/doc/COMDATA.html b/contrib/rom-o-matic/doc/COMDATA.html
deleted file mode 100644
index a27e275..0000000
--- a/contrib/rom-o-matic/doc/COMDATA.html
+++ /dev/null
@@ -1 +0,0 @@
-Serial Console Data bits
diff --git a/contrib/rom-o-matic/doc/COMPARITY.html b/contrib/rom-o-matic/doc/COMPARITY.html
deleted file mode 100644
index 14f3595..0000000
--- a/contrib/rom-o-matic/doc/COMPARITY.html
+++ /dev/null
@@ -1 +0,0 @@
-Serial Console Parity: 0=None, 1=Odd, 2=Even
diff --git a/contrib/rom-o-matic/doc/COMPRESERVE.html b/contrib/rom-o-matic/doc/COMPRESERVE.html
deleted file mode 100644
index 6e41a10..0000000
--- a/contrib/rom-o-matic/doc/COMPRESERVE.html
+++ /dev/null
@@ -1 +0,0 @@
-Keep settings from a previous user of the serial port \ No newline at end of file
diff --git a/contrib/rom-o-matic/doc/COMSPEED.html b/contrib/rom-o-matic/doc/COMSPEED.html
deleted file mode 100644
index 32b6859..0000000
--- a/contrib/rom-o-matic/doc/COMSPEED.html
+++ /dev/null
@@ -1 +0,0 @@
-Serial Console Baud rate
diff --git a/contrib/rom-o-matic/doc/COMSTOP.html b/contrib/rom-o-matic/doc/COMSTOP.html
deleted file mode 100644
index ae3fd24..0000000
--- a/contrib/rom-o-matic/doc/COMSTOP.html
+++ /dev/null
@@ -1 +0,0 @@
-Serial Console Stop bits
diff --git a/contrib/rom-o-matic/doc/CONFIG_CMD.html b/contrib/rom-o-matic/doc/CONFIG_CMD.html
deleted file mode 100644
index 1256c06..0000000
--- a/contrib/rom-o-matic/doc/CONFIG_CMD.html
+++ /dev/null
@@ -1 +0,0 @@
-Option configuration console
diff --git a/contrib/rom-o-matic/doc/CONSOLE_PC_BIOS.html b/contrib/rom-o-matic/doc/CONSOLE_PC_BIOS.html
deleted file mode 100644
index 144eea3..0000000
--- a/contrib/rom-o-matic/doc/CONSOLE_PC_BIOS.html
+++ /dev/null
@@ -1 +0,0 @@
-Enable Default BIOS console
diff --git a/contrib/rom-o-matic/doc/CONSOLE_SERIAL.html b/contrib/rom-o-matic/doc/CONSOLE_SERIAL.html
deleted file mode 100644
index f35e2ff..0000000
--- a/contrib/rom-o-matic/doc/CONSOLE_SERIAL.html
+++ /dev/null
@@ -1 +0,0 @@
-Enable Serial port console
diff --git a/contrib/rom-o-matic/doc/CRYPTO_80211_WEP.html b/contrib/rom-o-matic/doc/CRYPTO_80211_WEP.html
deleted file mode 100644
index 26fdf8a..0000000
--- a/contrib/rom-o-matic/doc/CRYPTO_80211_WEP.html
+++ /dev/null
@@ -1 +0,0 @@
-Wireless WEP encryption support
diff --git a/contrib/rom-o-matic/doc/CRYPTO_80211_WPA.html b/contrib/rom-o-matic/doc/CRYPTO_80211_WPA.html
deleted file mode 100644
index b218a1e..0000000
--- a/contrib/rom-o-matic/doc/CRYPTO_80211_WPA.html
+++ /dev/null
@@ -1 +0,0 @@
-Wireless WPA encryption support
diff --git a/contrib/rom-o-matic/doc/CRYPTO_80211_WPA2.html b/contrib/rom-o-matic/doc/CRYPTO_80211_WPA2.html
deleted file mode 100644
index 947597d..0000000
--- a/contrib/rom-o-matic/doc/CRYPTO_80211_WPA2.html
+++ /dev/null
@@ -1 +0,0 @@
-Wireless WPA2 encryption support
diff --git a/contrib/rom-o-matic/doc/DHCP_CMD.html b/contrib/rom-o-matic/doc/DHCP_CMD.html
deleted file mode 100644
index a0c31c7..0000000
--- a/contrib/rom-o-matic/doc/DHCP_CMD.html
+++ /dev/null
@@ -1 +0,0 @@
-DHCP management commands
diff --git a/contrib/rom-o-matic/doc/DNS_RESOLVER.html b/contrib/rom-o-matic/doc/DNS_RESOLVER.html
deleted file mode 100644
index 1029b9c..0000000
--- a/contrib/rom-o-matic/doc/DNS_RESOLVER.html
+++ /dev/null
@@ -1 +0,0 @@
-DNS resolver
diff --git a/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_FTP.html b/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_FTP.html
deleted file mode 100644
index 7686d5d..0000000
--- a/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_FTP.html
+++ /dev/null
@@ -1 +0,0 @@
-File Transfer Protocol
diff --git a/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_HTTP.html b/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_HTTP.html
deleted file mode 100644
index c28d888..0000000
--- a/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_HTTP.html
+++ /dev/null
@@ -1 +0,0 @@
-Hypertext Transfer Protocol
diff --git a/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_TFTP.html b/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_TFTP.html
deleted file mode 100644
index f2b31b1..0000000
--- a/contrib/rom-o-matic/doc/DOWNLOAD_PROTO_TFTP.html
+++ /dev/null
@@ -1 +0,0 @@
-Trivial File Transfer Protocol
diff --git a/contrib/rom-o-matic/doc/IFMGMT_CMD.html b/contrib/rom-o-matic/doc/IFMGMT_CMD.html
deleted file mode 100644
index 0e2b2a5..0000000
--- a/contrib/rom-o-matic/doc/IFMGMT_CMD.html
+++ /dev/null
@@ -1 +0,0 @@
-Interface management commands
diff --git a/contrib/rom-o-matic/doc/IMAGE_BZIMAGE.html b/contrib/rom-o-matic/doc/IMAGE_BZIMAGE.html
deleted file mode 100644
index d85e5d0..0000000
--- a/contrib/rom-o-matic/doc/IMAGE_BZIMAGE.html
+++ /dev/null
@@ -1 +0,0 @@
-Linux bzImage image support
diff --git a/contrib/rom-o-matic/doc/IMAGE_CMD.html b/contrib/rom-o-matic/doc/IMAGE_CMD.html
deleted file mode 100644
index 6f5acb5..0000000
--- a/contrib/rom-o-matic/doc/IMAGE_CMD.html
+++ /dev/null
@@ -1 +0,0 @@
-Image management commands
diff --git a/contrib/rom-o-matic/doc/IMAGE_ELF.html b/contrib/rom-o-matic/doc/IMAGE_ELF.html
deleted file mode 100644
index 5e39e8b..0000000
--- a/contrib/rom-o-matic/doc/IMAGE_ELF.html
+++ /dev/null
@@ -1 +0,0 @@
-ELF image support
diff --git a/contrib/rom-o-matic/doc/IMAGE_MULTIBOOT.html b/contrib/rom-o-matic/doc/IMAGE_MULTIBOOT.html
deleted file mode 100644
index 6a092a2..0000000
--- a/contrib/rom-o-matic/doc/IMAGE_MULTIBOOT.html
+++ /dev/null
@@ -1 +0,0 @@
-MultiBoot image support
diff --git a/contrib/rom-o-matic/doc/IMAGE_NBI.html b/contrib/rom-o-matic/doc/IMAGE_NBI.html
deleted file mode 100644
index eb78e03..0000000
--- a/contrib/rom-o-matic/doc/IMAGE_NBI.html
+++ /dev/null
@@ -1 +0,0 @@
-NBI image support
diff --git a/contrib/rom-o-matic/doc/IMAGE_PXE.html b/contrib/rom-o-matic/doc/IMAGE_PXE.html
deleted file mode 100644
index bdca384..0000000
--- a/contrib/rom-o-matic/doc/IMAGE_PXE.html
+++ /dev/null
@@ -1 +0,0 @@
-PXE image support
diff --git a/contrib/rom-o-matic/doc/IMAGE_SCRIPT.html b/contrib/rom-o-matic/doc/IMAGE_SCRIPT.html
deleted file mode 100644
index 8741672..0000000
--- a/contrib/rom-o-matic/doc/IMAGE_SCRIPT.html
+++ /dev/null
@@ -1 +0,0 @@
-iPXE script image support
diff --git a/contrib/rom-o-matic/doc/IWMGMT_CMD.html b/contrib/rom-o-matic/doc/IWMGMT_CMD.html
deleted file mode 100644
index 0d5bd4a..0000000
--- a/contrib/rom-o-matic/doc/IWMGMT_CMD.html
+++ /dev/null
@@ -1 +0,0 @@
-Wireless interface management commands
diff --git a/contrib/rom-o-matic/doc/NMB_RESOLVER.html b/contrib/rom-o-matic/doc/NMB_RESOLVER.html
deleted file mode 100644
index a0bdc17..0000000
--- a/contrib/rom-o-matic/doc/NMB_RESOLVER.html
+++ /dev/null
@@ -1 +0,0 @@
-NMB resolver
diff --git a/contrib/rom-o-matic/doc/NVO_CMD.html b/contrib/rom-o-matic/doc/NVO_CMD.html
deleted file mode 100644
index 5346f3f..0000000
--- a/contrib/rom-o-matic/doc/NVO_CMD.html
+++ /dev/null
@@ -1 +0,0 @@
-Non-volatile option storage commands
diff --git a/contrib/rom-o-matic/doc/ROUTE_CMD.html b/contrib/rom-o-matic/doc/ROUTE_CMD.html
deleted file mode 100644
index 8114c26..0000000
--- a/contrib/rom-o-matic/doc/ROUTE_CMD.html
+++ /dev/null
@@ -1 +0,0 @@
-Routing table management commands
diff --git a/contrib/rom-o-matic/doc/SANBOOT_CMD.html b/contrib/rom-o-matic/doc/SANBOOT_CMD.html
deleted file mode 100644
index 2e9d840..0000000
--- a/contrib/rom-o-matic/doc/SANBOOT_CMD.html
+++ /dev/null
@@ -1 +0,0 @@
-SAN boot commands
diff --git a/contrib/rom-o-matic/flag-table.php b/contrib/rom-o-matic/flag-table.php
deleted file mode 100644
index fe81c80..0000000
--- a/contrib/rom-o-matic/flag-table.php
+++ /dev/null
@@ -1,531 +0,0 @@
-<?php // -*- Mode: PHP; -*-
-
-/**
- * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
- * Copyright (C) 2009 Entity Cyber, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-$ofmts = array
- ( "Floppy bootable image (.dsk)" => "dsk",
- "SYSLINUX-based bootable floppy image (.sdsk)" => "sdsk",
- "ISO bootable image (.iso)" => "iso",
- "ISO bootable image with legacy floppy emulation (.liso)" => "liso",
- "Linux kernel (SYSLINUX/GRUB/LILO) loadable image (.lkrn)" => "lkrn",
- "USB Keychain disk image (.usb)" => "usb",
- "ROM binary (flashable) image (.rom)" => "rom",
- "ROM binary (flashable) for problem PMM BIOSES (.hrom)" => "hrom",
- "PXE bootstrap loader image [Unload PXE stack] (.pxe)" => "pxe",
- "PXE bootstrap loader keep [Keep PXE stack method 1] (.kpxe)" => "kpxe",
- "PXE bootstrap loader keep [Keep PXE stack method 2] (.kkpxe)" => "kkpxe",
- );
-
-$flag_table = array (
-
- // Begin General Options:
-
- "HDR_MISC_OPTIONS"
- => array (
- "flag" => "HDR_MISC_OPTIONS",
- "hide_from_user" => "yes", // Hide even the header
- "type" => "header",
- "label" => "Miscellaneous Options"
- ),
-
- "PRODUCT_NAME"
- => array (
- "flag" => "PRODUCT_NAME",
- "hide_from_user" => "yes",
- "type" => "string",
- "value" => "",
- "cfgsec" => "general"
- ),
-
- "PRODUCT_SHORT_NAME"
- => array (
- "flag" => "PRODUCT_SHORT_NAME",
- "hide_from_user" => "yes",
- "type" => "string",
- "value" => "iPXE",
- "cfgsec" => "general"
- ),
-
- // End General Options:
-
- // Begin Console Options:
-
- "HDR_CONSOLE_OPTIONS"
- => array (
- "flag" => "HDR_CONSOLE_OPTIONS",
- "type" => "header",
- "label" => "Console Options"
- ),
-
- "CONSOLE_PCBIOS"
- => array (
- "flag" => "CONSOLE_PCBIOS",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "console"
- ),
-
- "CONSOLE_SERIAL"
- => array (
- "flag" => "CONSOLE_SERIAL",
- "type" => "on/off",
- "value" => "off",
- "cfgsec" => "console"
- ),
-
- "BANNER_TIMEOUT"
- => array (
- "flag" => "BANNER_TIMEOUT",
- "type" => "integer",
- "value" => "20",
- "cfgsec" => "general"
- ),
-
- "KEYBOARD_MAP"
- => array (
- "flag" => "KEYBOARD_MAP",
- "type" => "choice",
- "options" => array("al","az","bg","by","cf","cz","de","dk","es","et","fi","fr",
- "gr","hu","il","it","lt","mk","mt","nl","no","pl","pt","ro","ru","sg","sr",
- "th","ua","uk","us","wo"),
- "value" => "us",
- "cfgsec" => "console"
- ),
-
- "LOG_LEVEL"
- => array (
- "flag" => "LOG_LEVEL",
- "type" => "choice",
- "options" => array("LOG_NONE","LOG_EMERG","LOG_ALERT","LOG_CRIT","LOG_ERR",
- "LOG_WARNING","LOG_NOTICE","LOG_INFO","LOG_DEBUG","LOG_ALL"),
- "value" => "LOG_NONE",
- "cfgsec" => "console"
- ),
-
- // End Console Options
-
- // Begin Network Protocol Options:
-
- "HDR_NETWORK_PROTOCOL_OPTIONS"
- => array (
- "flag" => "HDR_NETWORK_PROTOCOL_OPTIONS",
- "hide_from_user" => "yes", // Hide even the header
- "type" => "header",
- "label" => "Network Protocol Options"
- ),
-
- "NET_PROTO_IPV4"
- => array (
- "flag" => "NET_PROTO_IPV4",
- "type" => "on/off",
- "value" => "on",
- "hide_from_user" => "yes",
- "cfgsec" => "general"
- ),
-
- // End Network Protocol Options
-
- // Begin Serial Port configuration
-
- "HDR_SERIAL_PORT_OPTIONS"
- => array (
- "flag" => "HDR_SERIAL_PORT_OPTIONS",
- "type" => "header",
- "label" => "Serial Port Options"
- ),
-
- "COMCONSOLE"
- => array (
- "flag" => "COMCONSOLE",
- "type" => "integer-hex", // e.g. 0x378
- "value" => "0x3F8",
- "cfgsec" => "serial"
- ),
-
- "COMPRESERVE"
- => array (
- "flag" => "COMPRESERVE",
- "type" => "on/off",
- "value" => "off",
- "cfgsec" => "serial"
- ),
-
- "COMSPEED"
- => array (
- "flag" => "COMSPEED",
- "type" => "integer",
- "value" => "115200",
- "cfgsec" => "serial"
- ),
-
- "COMDATA"
- => array (
- "flag" => "COMDATA",
- "type" => "integer",
- "value" => "8",
- "cfgsec" => "serial"
- ),
-
- "COMPARITY"
- => array (
- "flag" => "COMPARITY",
- "type" => "integer",
- "value" => "0",
- "cfgsec" => "serial"
- ),
-
- "COMSTOP"
- => array (
- "flag" => "COMSTOP",
- "type" => "integer",
- "value" => "1",
- "cfgsec" => "serial"
- ),
-
- // End Serial Options
-
- // Begin Download Protocols
-
- "HDR_DOWNLOAD_PROTOCOLS"
- => array (
- "flag" => "HDR_DOWNLOAD_PROTOCOLS",
- "type" => "header",
- "label" => "Download Protocols"
- ),
-
- "DOWNLOAD_PROTO_TFTP"
- => array (
- "flag" => "DOWNLOAD_PROTO_TFTP",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "DOWNLOAD_PROTO_HTTP"
- => array (
- "flag" => "DOWNLOAD_PROTO_HTTP",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "DOWNLOAD_PROTO_HTTPS"
- => array (
- "flag" => "DOWNLOAD_PROTO_HTTPS",
- "type" => "on/off",
- "value" => "off",
- "cfgsec" => "general"
- ),
-
- "DOWNLOAD_PROTO_FTP"
- => array (
- "flag" => "DOWNLOAD_PROTO_FTP",
- "type" => "on/off",
- "value" => "off",
- "cfgsec" => "general"
- ),
-
- // End Download Protocols
-
- // Begin SAN boot protocols
-
- "HDR_SANBOOT_PROTOCOLS"
- => array (
- "flag" => "HDR_SANBOOT_PROTOCOLS",
- "type" => "header",
- "label" => "SAN Boot Protocols"
- ),
-
- "SANBOOT_PROTO_ISCSI"
- => array (
- "flag" => "SANBOOT_PROTO_ISCSI",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "SANBOOT_PROTO_AOE"
- => array (
- "flag" => "SANBOOT_PROTO_AOE",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- // End SAN boot protocols
-
- // Begin Name resolution modules
-
- "HDR_NAME_RESOLUTION_MODULES"
- => array (
- "flag" => "HDR_NAME_RESOLUTION_MODULES",
- "type" => "header",
- "label" => "Name Resolution Modules"
- ),
-
- "DNS_RESOLVER"
- => array (
- "flag" => "DNS_RESOLVER",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "NMB_RESOLVER"
- => array (
- "flag" => "NMB_RESOLVER",
- "type" => "on/off",
- "value" => "off",
- "hide_from_user" => "yes",
- "cfgsec" => "general"
- ),
-
- // End Name resolution modules
-
- // Begin Image types
-
- "HDR_IMAGE_TYPES"
- => array (
- "flag" => "HDR_IMAGE_TYPES",
- "type" => "header",
- "label" => "Image Types",
- ),
-
- "IMAGE_ELF"
- => array (
- "flag" => "IMAGE_ELF",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "IMAGE_NBI"
- => array (
- "flag" => "IMAGE_NBI",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "IMAGE_MULTIBOOT"
- => array (
- "flag" => "IMAGE_MULTIBOOT",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "IMAGE_PXE"
- => array (
- "flag" => "IMAGE_PXE",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "IMAGE_SCRIPT"
- => array (
- "flag" => "IMAGE_SCRIPT",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "IMAGE_BZIMAGE"
- => array (
- "flag" => "IMAGE_BZIMAGE",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "IMAGE_COMBOOT"
- => array (
- "flag" => "IMAGE_COMBOOT",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- // End Image types
-
- // Begin Command-line commands to include
-
- "HDR_COMMAND_LINE_OPTIONS"
- => array (
- "flag" => "HDR_COMMAND_LINE_OPTIONS",
- "type" => "header",
- "label" => "Command Line Options",
- ),
-
- "AUTOBOOT_CMD"
- => array (
- "flag" => "AUTOBOOT_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "NVO_CMD"
- => array (
- "flag" => "NVO_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "CONFIG_CMD"
- => array (
- "flag" => "CONFIG_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "IFMGMT_CMD"
- => array (
- "flag" => "IFMGMT_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "IWMGMT_CMD"
- => array (
- "flag" => "IWMGMT_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "ROUTE_CMD"
- => array (
- "flag" => "ROUTE_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "IMAGE_CMD"
- => array (
- "flag" => "IMAGE_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "DHCP_CMD"
- => array (
- "flag" => "DHCP_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "SANBOOT_CMD"
- => array (
- "flag" => "SANBOOT_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "LOGIN_CMD"
- => array (
- "flag" => "LOGIN_CMD",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "TIME_CMD"
- => array (
- "flag" => "TIME_CMD",
- "type" => "on/off",
- "value" => "off",
- "cfgsec" => "general"
- ),
-
- "DIGEST_CMD"
- => array (
- "flag" => "DIGEST_CMD",
- "type" => "on/off",
- "value" => "off",
- "cfgsec" => "general"
- ),
-
- // End Command-line commands to include
-
- // Begin Wireless options
-
- "HDR_WIRELESS_OPTIONS"
- => array (
- "flag" => "HDR_WIRELESS_OPTIONS",
- "type" => "header",
- "label" => "Wireless Interface Options",
- ),
-
- "CRYPTO_80211_WEP"
- => array (
- "flag" => "CRYPTO_80211_WEP",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "CRYPTO_80211_WPA"
- => array (
- "flag" => "CRYPTO_80211_WPA",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- "CRYPTO_80211_WPA2"
- => array (
- "flag" => "CRYPTO_80211_WPA2",
- "type" => "on/off",
- "value" => "on",
- "cfgsec" => "general"
- ),
-
- // End Wireless options
-
- // Obscure options required to compile
- "NETDEV_DISCARD_RATE"
- => array (
- "flag" => "NETDEV_DISCARD_RATE",
- "type" => "integer",
- "value" => "0",
- "cfgsec" => "general",
- "hide_from_user" => true
- )
-
- // End Obscure options
-);
-
-// For emacs:
-// Local variables:
-// c-basic-offset: 4
-// c-indent-level: 4
-// tab-width: 4
-// End:
-
-?>
diff --git a/contrib/rom-o-matic/globals.php b/contrib/rom-o-matic/globals.php
deleted file mode 100644
index 822e4bc..0000000
--- a/contrib/rom-o-matic/globals.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php // -*- Mode: PHP; -*-
-
-/**
- * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
- * Copyright (C) 2009 Entity Cyber, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-// Directory containing iPXE source code tree
-$src_dir = "../../src";
-
-// Compute iPXE version based on source tree
-exec ( "make -C '$src_dir' version 2>&1", $make_output, $status );
-$version = ( $status == 0 && count ( $make_output ) > 1 )
- ? trim ( $make_output[count ( $make_output ) - 2] )
- : "";
-
-// Email address of person responsible for this website
-$webmaster_email = "webmaster@example.com";
-
-// Files that header and footer text
-$top_inc = "top.php";
-$bottom_inc = "bottom.php";
-
-// Descriptive strings
-$header_title = "ROM-o-matic for iPXE $version";
-$html_tagline = "ROM-o-matic dynamically generates iPXE images";
-$html_title = "ROM-o-matic for iPXE $version";
-$description = "a dynamic iPXE image generator";
-
-// For emacs:
-// Local variables:
-// c-basic-offset: 4
-// c-indent-level: 4
-// tab-width: 4
-// End:
-
-?>
diff --git a/contrib/rom-o-matic/index.php b/contrib/rom-o-matic/index.php
deleted file mode 100644
index 26585c9..0000000
--- a/contrib/rom-o-matic/index.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php // -*- Mode: PHP; -*-
-
-/**
- * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
- * Copyright (C) 2009 Entity Cyber, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-// Get utility functions and set globals
-require_once "utils.php";
-
-// Begin html output
-include_once $top_inc;
-
-?>
-<form action="build.php" method=POST>
- <input type="hidden" name="version" value = "<?php echo $version ?>">
- <h3>To create an image:</h3>
- <ol>
- <?php require ( "directions.php" ); ?>
- <li>
- Generate and download an image:
- <input type="submit" name="A" value="Get Image">
- <br><br>
- </li>
- <li>
- (optional) Customize image configuration options:
- <input type="submit" name="A" value="Customize">
- <br><br>
- </li>
- </ol>
-</form>
-
-<?php include_once $bottom_inc ?>
diff --git a/contrib/rom-o-matic/top.php b/contrib/rom-o-matic/top.php
deleted file mode 100644
index 42a8e2d..0000000
--- a/contrib/rom-o-matic/top.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-
-<?php
-
-/**
- * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
- * Copyright (C) 2009 Entity Cyber, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-?>
-
-<html>
-<head>
- <link rev="made" href="mailto:<?php echo "${webmaster_email}" ?>">
- <meta name="keywords" content="rom, etherboot, ipxe, open source, rom-o-matic.net">
- <title><?php echo $header_title ?></title>
- <meta name="description" content="<?php echo $description ?>">
-</head>
-<h1>
-<?php echo "$html_title" ?>&nbsp;
-</h1>
-<hr>
-<h2>
-<?php echo "$html_tagline" ?>
-</h2>
-</form>
-<hr>
diff --git a/contrib/rom-o-matic/utils.php b/contrib/rom-o-matic/utils.php
deleted file mode 100644
index e0e62f4..0000000
--- a/contrib/rom-o-matic/utils.php
+++ /dev/null
@@ -1,684 +0,0 @@
-<?php // -*- Mode: PHP; -*-
-
-/**
- * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
- * Copyright (C) 2009 Entity Cyber, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-// Include table of user-configurable iPXE options
-require_once "flag-table.php";
-
-// Include user-shadowable globals
-require_once "globals.php";
-
-// Allow user to shadow globals
-if ( is_file ( 'local-config.php' ) ) {
- include_once "local-config.php";
-}
-
-////
-// General utility functions
-////
-
-/**
- * Remove undesirable characters from a given string
- *
- * Certain characters have the potential to be used for
- * malicious purposes by web-based attackers. This routine
- * filters out such characters.
- *
- * @param string $s supplied string
- *
- * @return string returned string with unwanted characters
- * removed
- */
-function cleanstring ( $s )
-{
- $len = strlen ( $s );
- if ( $len > 80 ) {
- $s = substr ( $s, 0, 80 );
- }
-
- $s = trim ( $s );
- $pos = 0;
- $result = "";
-
- while ( $pos < $len ) {
- $ltr = ord ( ucfirst ( $s[$pos] ) );
- if ( ( $ltr >= ord ( "A" ) ) && ( $ltr <= ord ( "Z" ) ) ||
- ( $ltr >= ord ( "0" ) ) && ( $ltr <= ord ( "9" ) ) ||
- ( $ltr == ord ( "." ) ) && ( strlen ( $result ) > 0 ) ||
- ( $ltr == ord ( "_" ) ) ||
- ( $ltr == ord ( "+" ) ) ||
- ( $ltr == ord ( ":" ) ) ||
- ( $ltr == ord ( "/" ) ) ||
- ( $ltr == ord ( "-" ) ) ) {
- $result .= $s[$pos];
- }
- $pos++;
- }
- return $result;
-}
-
-/**
- * Return URL of the currently running script, minus the filename
- *
- * @return string the URL of the currently running script, minus the filename
- */
-function curDirURL ()
-{
- $dir = dirname ( $_SERVER['PHP_SELF'] );
-
- if ( $dir == "." || $dir == "/" ) {
- $dir = "";
- }
-
- $isHTTPS = ( isset ( $_SERVER["HTTPS"] ) && $_SERVER["HTTPS"] == "on" );
- $port = ( isset($_SERVER["SERVER_PORT"] ) &&
- ( ( !$isHTTPS && $_SERVER["SERVER_PORT"] != "80" ) ||
- ( $isHTTPS && $_SERVER["SERVER_PORT"] != "443" ) ) );
-
- $port = ( $port ) ? ':' . $_SERVER["SERVER_PORT"] : '';
-
- $dest = ( $isHTTPS ? 'https://' : 'http://' ) .
- $_SERVER["SERVER_NAME"] . $dir . "/";
-
- return $dest;
-}
-
-/**
- * Extract NIC families and associated ROM PCI IDs from the src/bin/NIC file.
- *
- * $src_dir must contain the path of the iPXE src directory for this build
- *
- * @return array[0] array $new_nics
- * @return array[1] array $roms
- */
-function parse_nic_file ()
-{
- global $src_dir;
-
- $fd = fopen ( "$src_dir/bin/NIC", "r" );
- if ( ! $fd ) {
- die ( "Missing src/bin/NIC file. 'make bin/NIC'" );
- }
-
- $nics = array ();
- $roms = array ();
- $nic = "";
-
- while ( !feof ( $fd ) ) {
-
- $line = trim ( fgets ( $fd, 200 ) );
-
- $first_eight_chars = substr ( $line, 0, 8 );
- settype ( $first_eight_chars, "string" );
-
- if ( strpos ( $first_eight_chars, "family" ) === 0 ) {
-
- // get pathname of NIC driver
- #list ( $dummy, $nic ) = split( "[ \t]+", $line );
- list ( $dummy, $nic ) = explode("\t", $line);
- settype ( $nic, "string" );
-
- // extract filename name of driver from pathname
- $nic = substr ( $nic, strrpos ( $nic, "/" ) + 1,
- strlen ( $nic ) - strrpos ( $nic, "/" ) + 1 );
-
- $nics[$nic] = $nic;
-
- // For each ISA NIC, there can only be one ROM variant
- $roms[$nic] = $nic;
- }
-
- // If the first 8 digits of the line are hex digits
- // add this rom to the current nic family.
-
- if ( ( strlen ( $first_eight_chars ) == 8 )
- && ( ctype_xdigit ( $first_eight_chars ) )
- && ( $nic != "" ) ) {
-
- $roms[$first_eight_chars] = $nic;
- }
- }
- fclose ( $fd );
-
- // put most NICs in nice alpha order for menu
- ksort ( $nics );
-
- // add special cases to the top
-
- $new_nics = array ( "all-drivers" => "ipxe",
- "undionly" => "undionly",
- "undi" => "undi",
- );
-
- foreach ( $nics as $key => $value ) {
- // skip the undi driver
- if ( $key != "undi" ) {
- $new_nics[$key] = $value;
- }
- }
-
- return array ( $new_nics, $roms );
-}
-
-////
-// HTML form utility functions
-////
-
-/**
- * Return html code to create hidden form input fields
- *
- * @param string $flag name of form variable to set
- * @param string $value value to give form variable
- *
- * @return string html code for given hidden form input field
- */
-function hidden ( $flag, $value )
-{
- $value = htmlentities ( $value );
- return "<input type=\"hidden\" value=\"$value\" name=\"$flag\"></input>";
-}
-
-/**
- * Return html code to create checkbox form input fields
- *
- * @param string $flag name of form variable to set
- * @param string $value "on" means box should be checked
- *
- * @return string html code for given hidden form input field
- */
-function checkbox ( $flag, $value )
-{
- return "<input type=\"checkbox\" value=\"on\" name=\"$flag\"" .
- ($value == "on" ? " checked>" : ">" );
-}
-
-/**
- * Return html code to create text form input fields
- *
- * @param string $flag name of form variable to set
- * @param string $value initial contents of field
- * @param string $size size in characters of text box
- *
- * @return string html code for given text input field
- */
-function textbox ( $flag, $value, $size )
-{
- $value = htmlentities ( $value );
- return "<input type=\"text\" size=\"$size\" value=\"$value\" name=\"$flag\">";
-}
-
-/**
- * Return html code to create textarea form fields
- *
- * @param string $flag name of form variable to set
- * @param string $value initial contents of textarea
- * @param string $rows height of text area in rows
- * @param string $cols width of text area in columns
- *
- * @return string html code for given textarea input field
- */
-function textarea ( $flag, $value, $rows, $cols )
-{
- $value = htmlentities ( $value );
- return "<textarea name=\"$flag\" rows=\"$rows\" cols=\"$cols\">"
- . $value . "</textarea>";
-}
-
-/**
- * Return html code to create select (menu) form fields
- *
- * Use array of strings as menu choices
- *
- * @param string $flag name of form variable to set
- * @param array $options array of strings representing choices
- * @param string $value value of choice to select in menu
- *
- * @return string html code for given select (menu) input field
- */
-function menubox ( $name, $options, $value )
-{
- $s="<select name=\"$name\">";
-
- foreach ( $options as $ignore => $option ) {
- if ( !$value ) $value = $option;
- $s .= "<option" . ( $option == $value ? " selected>" : ">" ) .
- htmlentities ( $option ) . "</option>";
- }
- return $s . "</select>";
-}
-
-/**
- * Return html code to create select (menu) form fields
- *
- * Use indices of array of strings as menu choices rather than
- * the values pointed to by the indicies.
- *
- * @param string $flag name of form variable to set
- * @param array $options array of strings representing choices
- * @param string $value value of choice to select in menu
- *
- * @return string html code for given select (menu) input field
- */
-function keys_menubox ( $name, $options, $value )
-{
- $s="<select name=\"$name\">";
-
- foreach ( $options as $option => $ignore ) {
- if ( !$value ) $value = $option;
- $s .= "<option" . ( $option == $value ? " selected>" : ">" ) .
- htmlentities ( $option ) . "</option>";
- }
- return $s . "</select>";
-}
-
-////
-// Flag (compile option) handling functions
-////
-
-/**
- * Return default compile options (flags)
- *
- * Initial compile options are in a global called $flag_table.
- * Create and return an array containing the ones we want.
- *
- * @return array default compile options (flags)
- */
-function default_flags ()
-{
- global $flag_table;
-
- $flags = array ();
-
- foreach ( $flag_table as $key => $props ) {
-
- $flag = $props["flag"];
- $type = $props["type"];
-
- // Fields like headers have no "value" property
- if ( isset ( $props["value"] ) ) {
- $flags[$flag] = $props["value"];
- }
- }
- return $flags;
-}
-
-/**
- * Return combination of default and user compile options (flags)
- *
- * Initial compile options are in a global called $flag_table.
- * Compile options may have been changed via form input. We return
- * an array with either the default value of each option or a user
- * supplied value from form input.
- *
- * @return array combined default and user supplied compile options (flags)
- */
-function get_flags ()
-{
- global $flag_table;
-
- $flags = default_flags ();
-
- if ( ! isset ( $_POST["use_flags"] ) )
- return $flags;
-
- foreach ( $flag_table as $key => $props ) {
-
- $flag = $props["flag"];
- $type = $props["type"];
-
- if ( isset ( $_POST["$flag"] ) ) {
- $flags[$flag] = $_POST["$flag"];
- if ( $type == "integer-hex" ) {
- if ( strtolower ( substr ( $flags[$flag], 0, 2 ) ) != "0x" ) {
- $flags[$flag] = "0x" . $flags[$flag];
- }
- }
- } else if ( $type == "on/off" ) {
- // Unchecked checkboxes don't pass any POST value
- // so we must check for them specially. At this
- // point we know that there is no $_POST value set
- // for this option. If it is a checkbox, this means
- // it is unchecked, so record that in $flags so we
- // can later generate an #undef for this option.
- $flags[$flag] = "off";
- }
- }
- return $flags;
-}
-
-/**
- * Output given value in appropriate format for iPXE config file
- *
- * iPXE config/*.h files use C pre-processor syntax. Output the given
- * compile option in a format appropriate to its type
- *
- * @param string $key index into $flag_table for given compile option
- * @param string $value value we wish to set compile option to
- *
- * @return string code to set compile option to given value
- */
-function pprint_flag ( $key, $value )
-{
- global $flag_table;
-
- // Determine type of given compile option (flag)
- $type = $flag_table[$key]["type"];
- $s = "";
-
- if ( $type == "on/off" && $value == "on" ) {
- $s = "#define $key";
- } else if ( $type == "on/off" && $value != "on" ) {
- $s = "#undef $key";
- } else if ( $type == "string" ) {
- $s = ( "#define $key \"" . cleanstring ( $value ) . "\"" );
- } else if ($type == "qstring" ) {
- $s = ( "#define $key \\\"" . cleanstring ( $value ) . "\\\"" );
- } else {
- $s = "#define $key " . cleanstring ( $value );
- }
-
- return $s;
-}
-
-/**
- * Output html code to display all compile options as a table
- *
- * @param array $flags array of compile options
- *
- * @return void
- */
-function echo_flags ( $flags )
-{
- global $flag_table;
-
- echo "<table>\n";
-
- foreach ( $flag_table as $key => $props ) {
-
- // Hide parameters from users that should not be changed.
- $hide_from_user = isset ( $props["hide_from_user"] ) ? $props["hide_from_user"] : "no";
-
- $flag = $props["flag"];
- $type = $props["type"];
-
- $value = isset ( $flags[$flag] ) ? $flags[$flag] : '';
-
- if ( $hide_from_user == "yes" ) {
-
- // Hidden flags cannot not be set by the user. We use hidden form
- // fields to keep them at their default values.
- if ( $type != "header" ) {
- echo hidden ( $flag, $value );
- }
-
- } else {
-
- // Flag (iPXE compile option) should be displayed to user
-
- if ( $type == "header" ) {
-
- $label = $props["label"];
- echo "<td colspan=2><hr><h3>$label</h3><hr></td>";
-
- } else if ($type == "on/off" ) {
-
- echo "<td>", checkbox ( $flag, $value ), "</td><td><strong>$flag</strong></td>";
-
- } else { // don't display checkbox for non-on/off flags
-
- echo "<td>&nbsp;</td><td><strong>$flag: </strong>";
-
- if ($type == "choice" ) {
- $options = $props["options"];
- echo menubox($flag, $options, $value);
-
- } else {
-
- echo textbox($flag, $value, ($type == "integer" ||
- $type == "integer-hex"
- ? 7 : 25));
- }
- echo "</td>";
- }
- echo "</tr>\n";
-
- if ( $type != "header" ) {
- echo "<tr><td>&nbsp;</td>";
- echo "<td>\n";
- if ( is_file ( "doc/$flag.html" ) ) {
- include_once "doc/$flag.html";
- }
- echo "\n</td></tr>\n";
- }
- }
- }
- echo "</table>";
-}
-
-/**
- * Return an array of configuration sections used in all compile options
- *
- * $flag_table, the global list of compile options contains a 'cfgsec'
- * property for each flag we are interested in. We return a list of
- * all the unique cfgsec options we find in $flag_table.
- *
- * @return array an array of strings representing all unique cfgsec values
- * found in $flag_table
- */
-function get_flag_cfgsecs ()
-{
- global $flag_table;
- $cfgsecs = array ();
-
- foreach ( $flag_table as $key => $props ) {
- if ( isset ( $props['cfgsec'] ) ) {
- $cfgsec = $props["cfgsec"];
- $cfgsecs[$cfgsec] = $cfgsec;
- }
- }
- return $cfgsecs;
-}
-
-////
-// File and directory handling functions
-////
-
-/**
- * Create a copy of a given source directory to a given destination
- *
- * Since we are going to modify the source directory, we create a copy
- * of the directory with a unique name in the given destination directory.
- * We supply a prefix for the tempnam call to prepend to the random filename
- * it generates.
- *
- * @param string $src source directory
- * @param string $dst destination directory
- * @param string $prefix string to append to directory created
- *
- * @return string absolute path to destination directory
- */
-function mktempcopy ( $src, $dst, $prefix )
-{
- if ( $src[0] != "/" ) {
- $src = dirname ( $_SERVER['SCRIPT_FILENAME'] ) . "/" . $src;
- }
-
- // Create a file in the given destination directory with a unique name
- $dir = tempnam ( $dst, $prefix );
-
- // Delete the file just created, since it would interfere with the copy we
- // are about to do. We only care that the dir name we copy to is unique.
- unlink ( $dir );
-
- exec ( "/bin/cp -a '$src' '$dir' 2>&1", $cpytxt, $status );
-
- if ( $status != 0 ) {
- die ( "src directory copy failed!" );
- }
- return $dir;
-}
-
-/**
- * Write iPXE config files based on value of given flags
- *
- * iPXE compile options are stored in src/config/*.h .
- * We write out a config file for each set of options.
- *
- * @param string $config_dir directory to write .h files to
- * @param array $flags array of compile options for this build
- *
- * @return void
- */
-function write_ipxe_config_files ( $config_dir, $flags )
-{
- global $flag_table;
-
- $cfgsecs = get_flag_cfgsecs ();
-
- foreach ( $cfgsecs as $cfgsec ) {
-
- $fname = $config_dir . "/" . $cfgsec . ".h";
-
- $fp = fopen ( $fname, "wb" );
- if ( $fp <= 0 ) {
- die ( "Unable to open $fname file for output!" );
- }
-
- $ifdef_secname = "CONFIG_" . strtoupper ( $cfgsec ) . "_H";
-
- fwrite ( $fp, "#ifndef ${ifdef_secname}\n" );
- fwrite ( $fp, "#define ${ifdef_secname}\n" );
- fwrite ( $fp, "#include <config/defaults.h>\n" );
-
- foreach ( $flags as $key => $value ) {
- // When the flag matches this section name, write it out
- if ( $flag_table[$key]["cfgsec"] == $cfgsec ) {
- fwrite ( $fp, pprint_flag ( $key, $value ) . "\n" );
- }
- }
- fwrite ( $fp, "#endif /* ${ifdef_secname} */\n" );
- fclose ( $fp );
- }
-}
-
-/**
- * Output a string to a file
- *
- * Output a given string to a given pathname. The file will be created if
- * necessary, and the string will replace the file's contents in all cases.
- *
- * @param string $fname pathname of file to output string to
- * @param string $ftext text to output to file
- *
- * @return void
- */
-function write_file_from_string ( $fname, $ftext )
-{
- $fp = fopen ( $fname, "wb" );
- if ( ! $fp ) {
- die ( "Unable to open $fname file for output!" );
- }
- fwrite ( $fp, $ftext );
- fclose ( $fp );
-}
-
-/**
- * Delete a file or recursively delete a directory tree
- *
- * @param string $file_or_dir_name name of file or directory to delete
- * @return bool Returns TRUE on success, FALSE on failure
- */
-function rm_file_or_dir ( $file_or_dir_name )
-{
- if ( ! file_exists ( $file_or_dir_name ) ) {
- return false;
- }
-
- if ( is_file ( $file_or_dir_name ) || is_link ( $file_or_dir_name ) ) {
- return unlink ( $file_or_dir_name );
- }
-
- $dir = dir ( $file_or_dir_name );
- while ( ( $dir_entry = $dir->read () ) !== false ) {
-
- if ( $dir_entry == '.' || $dir_entry == '..') {
- continue;
- }
- rm_file_or_dir ( $file_or_dir_name . '/' . $dir_entry );
- }
- $dir->close();
-
- return rmdir ( $file_or_dir_name );
-}
-
-////
-// Debugging functions
-////
-
-/**
- * Emit html code to display given array of compile options (flags)
- *
- * @param array $flags array of compile options for this build
- *
- * @return void
- */
-function show_flags ( $flags )
-{
- echo ( "\$flags contains " . count ( $flags ) . " elements:" . "<br>" );
-
- foreach ( $flags as $key => $flag ) {
- echo ( "\$flags[" . $key . "]=" . "\"$flag\"" . "<br>" );
- }
-}
-
-/**
- * Emit HTML code to display default array of compile options (flags)
- *
- * $flag_table contains default compile options and properties. This
- * routine outputs HTML code to display all properties of $flag_table.
- *
- * @return void
- */
-function dump_flag_table ()
-{
- global $flag_table;
-
- echo ( "\$flag_table contains " . count ( $flag_table ) . " elements:" . "<br>" );
-
- foreach ( $flag_table as $key => $props ) {
- print ( "flag_table[" . $key . "] = " . "<br>" );
-
- foreach ( $props as $key2 => $props2 ) {
- print ( "&nbsp;&nbsp;&nbsp;" . $key2 . " = " . $props2 . "<br>" );
- }
- }
-}
-
-// Parse src/bin/NIC file
-list ( $nics, $roms ) = parse_nic_file ();
-
-// For emacs:
-// Local variables:
-// c-basic-offset: 4
-// c-indent-level: 4
-// tab-width: 4
-// End:
-
-?>
diff --git a/src/Makefile b/src/Makefile
index bc82cc6..9571962 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -77,6 +77,7 @@ SRCDIRS += drivers/net/efi
SRCDIRS += drivers/net/tg3
SRCDIRS += drivers/net/bnxt
SRCDIRS += drivers/net/sfc
+SRCDIRS += drivers/net/marvell
SRCDIRS += drivers/block
SRCDIRS += drivers/nvs
SRCDIRS += drivers/bitbash
diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping
index d13cb36..5d9c039 100644
--- a/src/Makefile.housekeeping
+++ b/src/Makefile.housekeeping
@@ -366,11 +366,6 @@ MAKEDEPS += arch/$(ARCH)/Makefile
include arch/$(ARCH)/Makefile
endif
-# Include architecture-specific include path
-ifdef ARCH
-INCDIRS += arch/$(ARCH)/include
-endif
-
###############################################################################
#
# Especially ugly workarounds
diff --git a/src/arch/arm/Makefile b/src/arch/arm/Makefile
index b6509dd..f827ed4 100644
--- a/src/arch/arm/Makefile
+++ b/src/arch/arm/Makefile
@@ -3,9 +3,9 @@
ASM_TCHAR := %
ASM_TCHAR_OPS := %%
-# Include common ARM headers
+# Include ARM-specific headers
#
-INCDIRS += arch/arm/include
+INCDIRS := arch/$(ARCH)/include arch/arm/include $(INCDIRS)
# ARM-specific directories containing source files
#
diff --git a/src/arch/arm/include/bits/acpi.h b/src/arch/arm/include/bits/acpi.h
deleted file mode 100644
index f9f2f00..0000000
--- a/src/arch/arm/include/bits/acpi.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_ACPI_H
-#define _BITS_ACPI_H
-
-/** @file
- *
- * ARM-specific ACPI API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_ACPI_H */
diff --git a/src/arch/arm/include/bits/hyperv.h b/src/arch/arm/include/bits/hyperv.h
deleted file mode 100644
index f0e0c87..0000000
--- a/src/arch/arm/include/bits/hyperv.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_HYPERV_H
-#define _BITS_HYPERV_H
-
-/** @file
- *
- * Hyper-V interface
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_HYPERV_H */
diff --git a/src/arch/arm/include/bits/iomap.h b/src/arch/arm/include/bits/iomap.h
deleted file mode 100644
index ae953c4..0000000
--- a/src/arch/arm/include/bits/iomap.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_IOMAP_H
-#define _BITS_IOMAP_H
-
-/** @file
- *
- * ARM-specific I/O mapping API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_IOMAP_H */
diff --git a/src/arch/arm/include/bits/mp.h b/src/arch/arm/include/bits/mp.h
deleted file mode 100644
index e7d4c0c..0000000
--- a/src/arch/arm/include/bits/mp.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_MP_H
-#define _BITS_MP_H
-
-/** @file
- *
- * ARM-specific multiprocessor API implementation
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_MP_H */
diff --git a/src/arch/arm/include/bits/pci_io.h b/src/arch/arm/include/bits/pci_io.h
deleted file mode 100644
index 91f507a..0000000
--- a/src/arch/arm/include/bits/pci_io.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_PCI_IO_H
-#define _BITS_PCI_IO_H
-
-/** @file
- *
- * ARM PCI I/O API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_PCI_IO_H */
diff --git a/src/arch/arm/include/bits/reboot.h b/src/arch/arm/include/bits/reboot.h
deleted file mode 100644
index 88c5025..0000000
--- a/src/arch/arm/include/bits/reboot.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_REBOOT_H
-#define _BITS_REBOOT_H
-
-/** @file
- *
- * ARM-specific reboot API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_REBOOT_H */
diff --git a/src/arch/arm/include/bits/sanboot.h b/src/arch/arm/include/bits/sanboot.h
deleted file mode 100644
index abd4c79..0000000
--- a/src/arch/arm/include/bits/sanboot.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_SANBOOT_H
-#define _BITS_SANBOOT_H
-
-/** @file
- *
- * ARM-specific sanboot API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_SANBOOT_H */
diff --git a/src/arch/arm/include/bits/smbios.h b/src/arch/arm/include/bits/smbios.h
deleted file mode 100644
index d942181..0000000
--- a/src/arch/arm/include/bits/smbios.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_SMBIOS_H
-#define _BITS_SMBIOS_H
-
-/** @file
- *
- * ARM-specific SMBIOS API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_SMBIOS_H */
diff --git a/src/arch/arm/include/bits/time.h b/src/arch/arm/include/bits/time.h
deleted file mode 100644
index 724d8b9..0000000
--- a/src/arch/arm/include/bits/time.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_TIME_H
-#define _BITS_TIME_H
-
-/** @file
- *
- * ARM-specific time API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_TIME_H */
diff --git a/src/arch/arm/include/bits/uaccess.h b/src/arch/arm/include/bits/uaccess.h
deleted file mode 100644
index 87f1150..0000000
--- a/src/arch/arm/include/bits/uaccess.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_UACCESS_H
-#define _BITS_UACCESS_H
-
-/** @file
- *
- * ARM-specific user access API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_UACCESS_H */
diff --git a/src/arch/arm/include/bits/uart.h b/src/arch/arm/include/bits/uart.h
deleted file mode 100644
index 6f85975..0000000
--- a/src/arch/arm/include/bits/uart.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_UART_H
-#define _BITS_UART_H
-
-/** @file
- *
- * 16550-compatible UART
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_UART_H */
diff --git a/src/arch/arm/include/bits/umalloc.h b/src/arch/arm/include/bits/umalloc.h
deleted file mode 100644
index 27970d7..0000000
--- a/src/arch/arm/include/bits/umalloc.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_UMALLOC_H
-#define _BITS_UMALLOC_H
-
-/** @file
- *
- * ARM-specific user memory allocation API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_UMALLOC_H */
diff --git a/src/arch/arm32/include/bits/tcpip.h b/src/arch/arm32/include/bits/tcpip.h
deleted file mode 100644
index fc3c5b3..0000000
--- a/src/arch/arm32/include/bits/tcpip.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _BITS_TCPIP_H
-#define _BITS_TCPIP_H
-
-/** @file
- *
- * Transport-network layer interface
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-static inline __attribute__ (( always_inline )) uint16_t
-tcpip_continue_chksum ( uint16_t partial, const void *data, size_t len ) {
-
- /* Not yet optimised */
- return generic_tcpip_continue_chksum ( partial, data, len );
-}
-
-#endif /* _BITS_TCPIP_H */
diff --git a/src/arch/arm32/include/gdbmach.h b/src/arch/arm32/include/gdbmach.h
deleted file mode 100644
index cd152ee..0000000
--- a/src/arch/arm32/include/gdbmach.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef GDBMACH_H
-#define GDBMACH_H
-
-/** @file
- *
- * GDB architecture specifics
- *
- * This file declares functions for manipulating the machine state and
- * debugging context.
- *
- */
-
-#include <stdint.h>
-
-typedef unsigned long gdbreg_t;
-
-/* Register snapshot */
-enum {
- /* Not yet implemented */
- GDBMACH_NREGS,
-};
-
-#define GDBMACH_SIZEOF_REGS ( GDBMACH_NREGS * sizeof ( gdbreg_t ) )
-
-static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) {
- /* Not yet implemented */
- ( void ) regs;
- ( void ) pc;
-}
-
-static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) {
- /* Not yet implemented */
- ( void ) regs;
- ( void ) step;
-}
-
-static inline void gdbmach_breakpoint ( void ) {
- /* Not yet implemented */
-}
-
-extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len,
- int enable );
-extern void gdbmach_init ( void );
-
-#endif /* GDBMACH_H */
diff --git a/src/arch/arm64/include/gdbmach.h b/src/arch/arm64/include/gdbmach.h
deleted file mode 100644
index cd152ee..0000000
--- a/src/arch/arm64/include/gdbmach.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef GDBMACH_H
-#define GDBMACH_H
-
-/** @file
- *
- * GDB architecture specifics
- *
- * This file declares functions for manipulating the machine state and
- * debugging context.
- *
- */
-
-#include <stdint.h>
-
-typedef unsigned long gdbreg_t;
-
-/* Register snapshot */
-enum {
- /* Not yet implemented */
- GDBMACH_NREGS,
-};
-
-#define GDBMACH_SIZEOF_REGS ( GDBMACH_NREGS * sizeof ( gdbreg_t ) )
-
-static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) {
- /* Not yet implemented */
- ( void ) regs;
- ( void ) pc;
-}
-
-static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) {
- /* Not yet implemented */
- ( void ) regs;
- ( void ) step;
-}
-
-static inline void gdbmach_breakpoint ( void ) {
- /* Not yet implemented */
-}
-
-extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len,
- int enable );
-extern void gdbmach_init ( void );
-
-#endif /* GDBMACH_H */
diff --git a/src/arch/i386/include/gdbmach.h b/src/arch/i386/include/bits/gdbmach.h
index 52cce78..52cce78 100644
--- a/src/arch/i386/include/gdbmach.h
+++ b/src/arch/i386/include/bits/gdbmach.h
diff --git a/src/arch/loong64/Makefile b/src/arch/loong64/Makefile
index fd0bf13..90d0ec8 100644
--- a/src/arch/loong64/Makefile
+++ b/src/arch/loong64/Makefile
@@ -18,6 +18,9 @@ endif
# EFI requires -fshort-wchar, and nothing else currently uses wchar_t
CFLAGS += -fshort-wchar
+# Include LoongArch64-specific headers
+INCDIRS := arch/$(ARCH)/include $(INCDIRS)
+
# LoongArch64-specific directories containing source files
SRCDIRS += arch/loong64/core
SRCDIRS += arch/loong64/interface/efi
diff --git a/src/arch/loong64/include/bits/acpi.h b/src/arch/loong64/include/bits/acpi.h
deleted file mode 100644
index 83dd1df..0000000
--- a/src/arch/loong64/include/bits/acpi.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_ACPI_H
-#define _BITS_ACPI_H
-
-/** @file
- *
- * LoongArch64-specific ACPI API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_ACPI_H */
diff --git a/src/arch/loong64/include/bits/hyperv.h b/src/arch/loong64/include/bits/hyperv.h
deleted file mode 100644
index f0e0c87..0000000
--- a/src/arch/loong64/include/bits/hyperv.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_HYPERV_H
-#define _BITS_HYPERV_H
-
-/** @file
- *
- * Hyper-V interface
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_HYPERV_H */
diff --git a/src/arch/loong64/include/bits/iomap.h b/src/arch/loong64/include/bits/iomap.h
deleted file mode 100644
index 041171d..0000000
--- a/src/arch/loong64/include/bits/iomap.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_IOMAP_H
-#define _BITS_IOMAP_H
-
-/** @file
- *
- * LoongArch64-specific I/O mapping API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_IOMAP_H */
diff --git a/src/arch/loong64/include/bits/mp.h b/src/arch/loong64/include/bits/mp.h
deleted file mode 100644
index fef2fd5..0000000
--- a/src/arch/loong64/include/bits/mp.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_MP_H
-#define _BITS_MP_H
-
-/** @file
- *
- * LoongArch64-specific multiprocessor API implementation
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_MP_H */
diff --git a/src/arch/loong64/include/bits/pci_io.h b/src/arch/loong64/include/bits/pci_io.h
deleted file mode 100644
index fdc5141..0000000
--- a/src/arch/loong64/include/bits/pci_io.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_PCI_IO_H
-#define _BITS_PCI_IO_H
-
-/** @file
- *
- * LoongArch64-specific PCI I/O API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_PCI_IO_H */
diff --git a/src/arch/loong64/include/bits/reboot.h b/src/arch/loong64/include/bits/reboot.h
deleted file mode 100644
index 96a1eb1..0000000
--- a/src/arch/loong64/include/bits/reboot.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_REBOOT_H
-#define _BITS_REBOOT_H
-
-/** @file
- *
- * LoongArch64-specific reboot API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_REBOOT_H */
diff --git a/src/arch/loong64/include/bits/sanboot.h b/src/arch/loong64/include/bits/sanboot.h
deleted file mode 100644
index f9205e2..0000000
--- a/src/arch/loong64/include/bits/sanboot.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_SANBOOT_H
-#define _BITS_SANBOOT_H
-
-/** @file
- *
- * LoongArch64-specific sanboot API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_SANBOOT_H */
diff --git a/src/arch/loong64/include/bits/smbios.h b/src/arch/loong64/include/bits/smbios.h
deleted file mode 100644
index 6c87db4..0000000
--- a/src/arch/loong64/include/bits/smbios.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_SMBIOS_H
-#define _BITS_SMBIOS_H
-
-/** @file
- *
- * LoongArch64-specific SMBIOS API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_SMBIOS_H */
diff --git a/src/arch/loong64/include/bits/tcpip.h b/src/arch/loong64/include/bits/tcpip.h
deleted file mode 100644
index fc3c5b3..0000000
--- a/src/arch/loong64/include/bits/tcpip.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _BITS_TCPIP_H
-#define _BITS_TCPIP_H
-
-/** @file
- *
- * Transport-network layer interface
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-static inline __attribute__ (( always_inline )) uint16_t
-tcpip_continue_chksum ( uint16_t partial, const void *data, size_t len ) {
-
- /* Not yet optimised */
- return generic_tcpip_continue_chksum ( partial, data, len );
-}
-
-#endif /* _BITS_TCPIP_H */
diff --git a/src/arch/loong64/include/bits/time.h b/src/arch/loong64/include/bits/time.h
deleted file mode 100644
index 4cd7485..0000000
--- a/src/arch/loong64/include/bits/time.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_TIME_H
-#define _BITS_TIME_H
-
-/** @file
- *
- * LoongArch64-specific time API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_TIME_H */
diff --git a/src/arch/loong64/include/bits/uaccess.h b/src/arch/loong64/include/bits/uaccess.h
deleted file mode 100644
index dddd9be..0000000
--- a/src/arch/loong64/include/bits/uaccess.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_UACCESS_H
-#define _BITS_UACCESS_H
-
-/** @file
- *
- * LoongArch64-specific user access API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_UACCESS_H */
diff --git a/src/arch/loong64/include/bits/uart.h b/src/arch/loong64/include/bits/uart.h
deleted file mode 100644
index 6f85975..0000000
--- a/src/arch/loong64/include/bits/uart.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_UART_H
-#define _BITS_UART_H
-
-/** @file
- *
- * 16550-compatible UART
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_UART_H */
diff --git a/src/arch/loong64/include/bits/umalloc.h b/src/arch/loong64/include/bits/umalloc.h
deleted file mode 100644
index f6978b8..0000000
--- a/src/arch/loong64/include/bits/umalloc.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _BITS_UMALLOC_H
-#define _BITS_UMALLOC_H
-
-/** @file
- *
- * LoongArch64-specific user memory allocation API implementations
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#endif /* _BITS_UMALLOC_H */
diff --git a/src/arch/x86/Makefile b/src/arch/x86/Makefile
index ef80136..4a4d8ee 100644
--- a/src/arch/x86/Makefile
+++ b/src/arch/x86/Makefile
@@ -3,9 +3,9 @@
ASM_TCHAR := @
ASM_TCHAR_OPS := @
-# Include common x86 headers
+# Include x86-specific headers
#
-INCDIRS += arch/x86/include
+INCDIRS := arch/$(ARCH)/include arch/x86/include $(INCDIRS)
# x86-specific directories containing source files
#
diff --git a/src/arch/x86/core/cpuid_settings.c b/src/arch/x86/core/cpuid_settings.c
index 0b67ee9..9bc69f4 100644
--- a/src/arch/x86/core/cpuid_settings.c
+++ b/src/arch/x86/core/cpuid_settings.c
@@ -38,7 +38,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* Bit 31 Extended function
* Bits 30-24 (bit 22 = 1) Subfunction number
- * (bit 22 = 0) Number of consecutive functions to call, minus one
+ * Bit 30 (bit 22 = 0) Hypervisor function
+ * Bits 29-24 (bit 22 = 0) Number of consecutive functions to call, minus one
* Bit 23 Return result as little-endian (used for strings)
* Bit 22 Interpret bits 30-24 as a subfunction number
* Bits 21-18 Unused
@@ -98,7 +99,7 @@ enum cpuid_flags {
* @v tag Setting tag
* @ret function Starting function number
*/
-#define CPUID_FUNCTION( tag ) ( (tag) & 0x800000ffUL )
+#define CPUID_FUNCTION( tag ) ( (tag) & 0xc00000ffUL )
/**
* Extract subfunction number from CPUID setting tag
@@ -109,6 +110,14 @@ enum cpuid_flags {
#define CPUID_SUBFUNCTION( tag ) ( ( (tag) >> 24 ) & 0x7f )
/**
+ * Extract number of consecutive functions from CPUID setting tag
+ *
+ * @v tag Setting tag
+ * @ret num_functions Number of consecutive functions
+ */
+#define CPUID_NUM_FUNCTIONS( tag ) ( ( ( (tag) >> 24 ) & 0x3f ) + 1 )
+
+/**
* Extract register array from CPUID setting tag
*
* @v tag Setting tag
@@ -165,12 +174,13 @@ static int cpuid_settings_fetch ( struct settings *settings,
/* Call each function in turn */
function = CPUID_FUNCTION ( setting->tag );
- subfunction = CPUID_SUBFUNCTION ( setting->tag );
if ( setting->tag & CPUID_USE_SUBFUNCTION ) {
+ function &= ~CPUID_HYPERVISOR;
+ subfunction = CPUID_SUBFUNCTION ( setting->tag );
num_functions = 1;
} else {
- num_functions = ( subfunction + 1 );
subfunction = 0;
+ num_functions = CPUID_NUM_FUNCTIONS ( setting->tag );
}
for ( ; num_functions-- ; function++ ) {
diff --git a/src/arch/x86/core/gdbmach.c b/src/arch/x86/core/gdbmach.c
index af6abfe..d4d187e 100644
--- a/src/arch/x86/core/gdbmach.c
+++ b/src/arch/x86/core/gdbmach.c
@@ -31,7 +31,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/uaccess.h>
#include <ipxe/gdbstub.h>
#include <librm.h>
-#include <gdbmach.h>
/** @file
*
diff --git a/src/arch/x86/core/pcidirect.c b/src/arch/x86/core/pcidirect.c
index f4659a1..90d4623 100644
--- a/src/arch/x86/core/pcidirect.c
+++ b/src/arch/x86/core/pcidirect.c
@@ -45,6 +45,7 @@ void pcidirect_prepare ( struct pci_device *pci, int where ) {
PCIDIRECT_CONFIG_ADDRESS );
}
+PROVIDE_PCIAPI_INLINE ( direct, pci_can_probe );
PROVIDE_PCIAPI_INLINE ( direct, pci_discover );
PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_word );
diff --git a/src/arch/x86/include/ipxe/pcibios.h b/src/arch/x86/include/ipxe/pcibios.h
index 3caea1c..ef95856 100644
--- a/src/arch/x86/include/ipxe/pcibios.h
+++ b/src/arch/x86/include/ipxe/pcibios.h
@@ -33,6 +33,16 @@ extern int pcibios_write ( struct pci_device *pci, uint32_t command,
uint32_t value );
/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_can_probe ) ( void ) {
+ return 1;
+}
+
+/**
* Read byte from PCI configuration space via PCI BIOS
*
* @v pci PCI device
diff --git a/src/arch/x86/include/ipxe/pcicloud.h b/src/arch/x86/include/ipxe/pcicloud.h
index 5226890..1feef56 100644
--- a/src/arch/x86/include/ipxe/pcicloud.h
+++ b/src/arch/x86/include/ipxe/pcicloud.h
@@ -15,4 +15,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define PCIAPI_PREFIX_cloud __cloud_
#endif
+/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( cloud, pci_can_probe ) ( void ) {
+ return 1;
+}
+
#endif /* _IPXE_PCICLOUD_H */
diff --git a/src/arch/x86/include/ipxe/pcidirect.h b/src/arch/x86/include/ipxe/pcidirect.h
index 98c6a2b..999b527 100644
--- a/src/arch/x86/include/ipxe/pcidirect.h
+++ b/src/arch/x86/include/ipxe/pcidirect.h
@@ -26,6 +26,16 @@ struct pci_device;
extern void pcidirect_prepare ( struct pci_device *pci, int where );
/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_can_probe ) ( void ) {
+ return 1;
+}
+
+/**
* Find next PCI bus:dev.fn address range in system
*
* @v busdevfn Starting PCI bus:dev.fn address
diff --git a/src/arch/x86/interface/pcbios/pcibios.c b/src/arch/x86/interface/pcbios/pcibios.c
index 7b7a769..ebe40ba 100644
--- a/src/arch/x86/interface/pcbios/pcibios.c
+++ b/src/arch/x86/interface/pcbios/pcibios.c
@@ -120,6 +120,7 @@ int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
return ( status >> 8 );
}
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_can_probe );
PROVIDE_PCIAPI ( pcbios, pci_discover, pcibios_discover );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word );
diff --git a/src/arch/x86/interface/pcbios/pcicloud.c b/src/arch/x86/interface/pcbios/pcicloud.c
index 98ba38b..f7d4a2d 100644
--- a/src/arch/x86/interface/pcbios/pcicloud.c
+++ b/src/arch/x86/interface/pcbios/pcicloud.c
@@ -148,6 +148,7 @@ static void * pcicloud_ioremap ( struct pci_device *pci,
return pcicloud->pci_ioremap ( pci, bus_addr, len );
}
+PROVIDE_PCIAPI_INLINE ( cloud, pci_can_probe );
PROVIDE_PCIAPI ( cloud, pci_discover, pcicloud_discover );
PROVIDE_PCIAPI ( cloud, pci_read_config_byte, pcicloud_read_config_byte );
PROVIDE_PCIAPI ( cloud, pci_read_config_word, pcicloud_read_config_word );
diff --git a/src/arch/x86_64/include/gdbmach.h b/src/arch/x86_64/include/bits/gdbmach.h
index 367405f..367405f 100644
--- a/src/arch/x86_64/include/gdbmach.h
+++ b/src/arch/x86_64/include/bits/gdbmach.h
diff --git a/src/config/config.c b/src/config/config.c
index 6bcd3c1..f532c1d 100644
--- a/src/config/config.c
+++ b/src/config/config.c
@@ -299,6 +299,9 @@ REQUIRE_OBJECT ( image_mem_cmd );
#ifdef SHIM_CMD
REQUIRE_OBJECT ( shim_cmd );
#endif
+#ifdef IMAGE_CRYPT_CMD
+REQUIRE_OBJECT ( image_crypt_cmd );
+#endif
/*
* Drag in miscellaneous objects
diff --git a/src/config/config_crypto.c b/src/config/config_crypto.c
index 5211224..f118a97 100644
--- a/src/config/config_crypto.c
+++ b/src/config/config_crypto.c
@@ -88,6 +88,16 @@ REQUIRE_OBJECT ( oid_sha512_256 );
REQUIRE_OBJECT ( oid_x25519 );
#endif
+/* AES-CBC */
+#if defined ( CRYPTO_CIPHER_AES_CBC )
+REQUIRE_OBJECT ( oid_aes_cbc );
+#endif
+
+/* AES-GCM */
+#if defined ( CRYPTO_CIPHER_AES_GCM )
+REQUIRE_OBJECT ( oid_aes_gcm );
+#endif
+
/* RSA and MD5 */
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_DIGEST_MD5 )
REQUIRE_OBJECT ( rsa_md5 );
diff --git a/src/config/general.h b/src/config/general.h
index f936e87..b82e560 100644
--- a/src/config/general.h
+++ b/src/config/general.h
@@ -158,6 +158,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
//#define REBOOT_CMD /* Reboot command */
//#define POWEROFF_CMD /* Power off command */
//#define IMAGE_TRUST_CMD /* Image trust management commands */
+//#define IMAGE_CRYPT_CMD /* Image encryption management commands */
//#define PCI_CMD /* PCI commands */
//#define PARAM_CMD /* Request parameter commands */
//#define NEIGHBOUR_CMD /* Neighbour management commands */
diff --git a/src/core/archive.c b/src/core/archive.c
index bb62c7e..3d3f00c 100644
--- a/src/core/archive.c
+++ b/src/core/archive.c
@@ -43,7 +43,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
int image_extract ( struct image *image, const char *name,
struct image **extracted ) {
- char *dot;
int rc;
/* Check that this image can be used to extract an archive image */
@@ -66,10 +65,8 @@ int image_extract ( struct image *image, const char *name,
}
/* Strip any archive or compression suffix from implicit name */
- if ( ( ! name ) && ( (*extracted)->name ) &&
- ( ( dot = strrchr ( (*extracted)->name, '.' ) ) != NULL ) ) {
- *dot = '\0';
- }
+ if ( ! name )
+ image_strip_suffix ( *extracted );
/* Try extracting archive image */
if ( ( rc = image->type->extract ( image, *extracted ) ) != 0 ) {
diff --git a/src/core/gdbstub.c b/src/core/gdbstub.c
index 8b57ddf..d668f45 100644
--- a/src/core/gdbstub.c
+++ b/src/core/gdbstub.c
@@ -36,7 +36,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ctype.h>
#include <byteswap.h>
#include <ipxe/gdbstub.h>
-#include "gdbmach.h"
enum {
POSIX_EINVAL = 0x1c, /* used to report bad arguments to GDB */
diff --git a/src/core/image.c b/src/core/image.c
index bf0e4f7..c69c05c 100644
--- a/src/core/image.c
+++ b/src/core/image.c
@@ -173,6 +173,25 @@ int image_set_name ( struct image *image, const char *name ) {
}
/**
+ * Strip dot suffix from image name, if present
+ *
+ * @v image Image
+ * @ret sep Position of old dot separator, or NULL
+ */
+char * image_strip_suffix ( struct image *image ) {
+ char *dot;
+
+ /* Locate and strip suffix, if present */
+ if ( image->name &&
+ ( ( dot = strrchr ( image->name, '.' ) ) != NULL ) ) {
+ *dot = '\0';
+ return dot;
+ }
+
+ return NULL;
+}
+
+/**
* Set image command line
*
* @v image Image
diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c
index dc9d1c5..aa57c6a 100644
--- a/src/crypto/asn1.c
+++ b/src/crypto/asn1.c
@@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <time.h>
#include <ipxe/tables.h>
#include <ipxe/image.h>
+#include <ipxe/crypto.h>
#include <ipxe/asn1.h>
/** @file
@@ -94,8 +95,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* object body (i.e. the first byte following the length byte(s)), and
* the length of the object body (i.e. the number of bytes until the
* following object tag, if any) is returned.
+ *
+ * If the expected type is not found, the object cursor will not be
+ * modified. If any other error occurs, the object cursor will be
+ * invalidated.
*/
-int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
+static int asn1_start ( struct asn1_cursor *cursor, unsigned int type,
+ size_t extra ) {
unsigned int len_len;
unsigned int len;
@@ -103,6 +109,7 @@ int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
if ( cursor->len )
DBGC ( cursor, "ASN1 %p too short\n", cursor );
+ asn1_invalidate_cursor ( cursor );
return -EINVAL_ASN1_EMPTY;
}
@@ -127,6 +134,7 @@ int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
if ( cursor->len < len_len ) {
DBGC ( cursor, "ASN1 %p bad length field length %d (max "
"%zd)\n", cursor, len_len, cursor->len );
+ asn1_invalidate_cursor ( cursor );
return -EINVAL_ASN1_LEN_LEN;
}
@@ -140,6 +148,7 @@ int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
if ( ( cursor->len + extra ) < len ) {
DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
cursor, len, ( cursor->len + extra ) );
+ asn1_invalidate_cursor ( cursor );
return -EINVAL_ASN1_LEN;
}
@@ -147,33 +156,59 @@ int asn1_start ( struct asn1_cursor *cursor, unsigned int type, size_t extra ) {
}
/**
- * Enter ASN.1 object
+ * Enter ASN.1 partial object
*
* @v cursor ASN.1 object cursor
* @v type Expected type, or ASN1_ANY
+ * @v extra Additional length beyond partial object
* @ret rc Return status code
*
- * The object cursor will be updated to point to the body of the
- * current ASN.1 object. If any error occurs, the object cursor will
- * be invalidated.
+ * The object cursor and additional length will be updated to point to
+ * the body of the current ASN.1 object.
+ *
+ * If any error occurs, the object cursor will be invalidated.
*/
-int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
+int asn1_enter_partial ( struct asn1_cursor *cursor, unsigned int type,
+ size_t *extra ) {
int len;
- len = asn1_start ( cursor, type, 0 );
+ /* Parse current object */
+ len = asn1_start ( cursor, type, *extra );
if ( len < 0 ) {
asn1_invalidate_cursor ( cursor );
return len;
}
- cursor->len = len;
+ /* Update cursor and additional length */
+ if ( ( ( size_t ) len ) <= cursor->len )
+ cursor->len = len;
+ assert ( ( len - cursor->len ) <= *extra );
+ *extra = ( len - cursor->len );
+
DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
cursor, type, len );
-
return 0;
}
/**
+ * Enter ASN.1 object
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type, or ASN1_ANY
+ * @ret rc Return status code
+ *
+ * The object cursor will be updated to point to the body of the
+ * current ASN.1 object.
+ *
+ * If any error occurs, the object cursor will be invalidated.
+ */
+int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
+ static size_t no_extra = 0;
+
+ return asn1_enter_partial ( cursor, type, &no_extra );
+}
+
+/**
* Skip ASN.1 object if present
*
* @v cursor ASN.1 object cursor
@@ -181,26 +216,26 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
* @ret rc Return status code
*
* The object cursor will be updated to point to the next ASN.1
- * object. If any error occurs, the object cursor will not be
- * modified.
+ * object.
+ *
+ * If the expected type is not found, the object cursor will not be
+ * modified. If any other error occurs, the object cursor will be
+ * invalidated.
*/
int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
int len;
+ /* Parse current object */
len = asn1_start ( cursor, type, 0 );
if ( len < 0 )
return len;
+ /* Update cursor */
cursor->data += len;
cursor->len -= len;
+
DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
cursor, type, len );
-
- if ( ! cursor->len ) {
- DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
- return -ENOENT;
- }
-
return 0;
}
@@ -212,8 +247,9 @@ int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
* @ret rc Return status code
*
* The object cursor will be updated to point to the next ASN.1
- * object. If any error occurs, the object cursor will be
- * invalidated.
+ * object.
+ *
+ * If any error occurs, the object cursor will be invalidated.
*/
int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
int rc;
@@ -234,8 +270,9 @@ int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
* @ret rc Return status code
*
* The object cursor will be shrunk to contain only the current ASN.1
- * object. If any error occurs, the object cursor will be
- * invalidated.
+ * object.
+ *
+ * If any error occurs, the object cursor will be invalidated.
*/
int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
struct asn1_cursor temp;
@@ -473,18 +510,26 @@ asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
*
* @v cursor ASN.1 object cursor
* @ret algorithm Algorithm
+ * @ret params Algorithm parameters, or NULL
* @ret rc Return status code
*/
int asn1_algorithm ( const struct asn1_cursor *cursor,
- struct asn1_algorithm **algorithm ) {
+ struct asn1_algorithm **algorithm,
+ struct asn1_cursor *params ) {
struct asn1_cursor contents;
int rc;
- /* Enter signatureAlgorithm */
+ /* Enter algorithm */
memcpy ( &contents, cursor, sizeof ( contents ) );
asn1_enter ( &contents, ASN1_SEQUENCE );
- /* Enter algorithm */
+ /* Get raw parameters, if applicable */
+ if ( params ) {
+ memcpy ( params, &contents, sizeof ( *params ) );
+ asn1_skip_any ( params );
+ }
+
+ /* Enter algorithm identifier */
if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
cursor );
@@ -500,6 +545,14 @@ int asn1_algorithm ( const struct asn1_cursor *cursor,
return -ENOTSUP_ALGORITHM;
}
+ /* Parse parameters, if applicable */
+ if ( params && (*algorithm)->parse &&
+ ( ( rc = (*algorithm)->parse ( *algorithm, params ) ) != 0 ) ) {
+ DBGC ( cursor, "ASN1 %p cannot parse %s parameters: %s\n",
+ cursor, (*algorithm)->name, strerror ( rc ) );
+ return rc;
+ }
+
return 0;
}
@@ -515,7 +568,7 @@ int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
int rc;
/* Parse algorithm */
- if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
+ if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
return rc;
/* Check algorithm has a public key */
@@ -541,7 +594,7 @@ int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
int rc;
/* Parse algorithm */
- if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
+ if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
return rc;
/* Check algorithm has a digest */
@@ -556,6 +609,34 @@ int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
}
/**
+ * Parse ASN.1 OID-identified cipher algorithm
+ *
+ * @v cursor ASN.1 object cursor
+ * @ret algorithm Algorithm
+ * @ret params Algorithm parameters, or NULL
+ * @ret rc Return status code
+ */
+int asn1_cipher_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm,
+ struct asn1_cursor *params ) {
+ int rc;
+
+ /* Parse algorithm */
+ if ( ( rc = asn1_algorithm ( cursor, algorithm, params ) ) != 0 )
+ return rc;
+
+ /* Check algorithm has a cipher */
+ if ( ! (*algorithm)->cipher ) {
+ DBGC ( cursor, "ASN1 %p algorithm %s is not a cipher "
+ "algorithm:\n", cursor, (*algorithm)->name );
+ DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+ return -ENOTTY_ALGORITHM;
+ }
+
+ return 0;
+}
+
+/**
* Parse ASN.1 OID-identified signature algorithm
*
* @v cursor ASN.1 object cursor
@@ -567,7 +648,7 @@ int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
int rc;
/* Parse algorithm */
- if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
+ if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
return rc;
/* Check algorithm has a public key */
@@ -602,7 +683,7 @@ int asn1_check_algorithm ( const struct asn1_cursor *cursor,
int rc;
/* Parse algorithm */
- if ( ( rc = asn1_algorithm ( cursor, &actual ) ) != 0 )
+ if ( ( rc = asn1_algorithm ( cursor, &actual, NULL ) ) != 0 )
return rc;
/* Check algorithm matches */
@@ -616,6 +697,47 @@ int asn1_check_algorithm ( const struct asn1_cursor *cursor,
}
/**
+ * Parse ASN.1 CBC cipher parameters
+ *
+ * @v algorithm Algorithm
+ * @v param Parameters to parse
+ * @ret rc Return status code
+ */
+int asn1_parse_cbc ( struct asn1_algorithm *algorithm,
+ struct asn1_cursor *params ) {
+ struct cipher_algorithm *cipher = algorithm->cipher;
+
+ /* Sanity check */
+ assert ( cipher != NULL );
+
+ /* Enter parameters */
+ asn1_enter ( params, ASN1_OCTET_STRING );
+
+ /* Check length */
+ if ( params->len != cipher->blocksize )
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * Parse ASN.1 GCM cipher parameters
+ *
+ * @v algorithm Algorithm
+ * @v param Parameters to parse
+ * @ret rc Return status code
+ */
+int asn1_parse_gcm ( struct asn1_algorithm *algorithm __unused,
+ struct asn1_cursor *params ) {
+
+ /* Enter parameters */
+ asn1_enter ( params, ASN1_SEQUENCE );
+
+ /* Enter nonce */
+ return asn1_enter ( params, ASN1_OCTET_STRING );
+}
+
+/**
* Parse ASN.1 GeneralizedTime
*
* @v cursor ASN.1 cursor
diff --git a/src/crypto/certstore.c b/src/crypto/certstore.c
index 2676c7e..31797c4 100644
--- a/src/crypto/certstore.c
+++ b/src/crypto/certstore.c
@@ -69,66 +69,28 @@ static struct asn1_cursor certstore_raw[] = {
static struct x509_certificate certstore_certs[ sizeof ( certstore_raw ) /
sizeof ( certstore_raw[0] ) ];
-/** Certificate store */
-struct x509_chain certstore = {
- .refcnt = REF_INIT ( ref_no_free ),
- .links = LIST_HEAD_INIT ( certstore.links ),
-};
-
/**
* Mark stored certificate as most recently used
*
+ * @v store Certificate store
* @v cert X.509 certificate
- * @ret cert X.509 certificate
*/
-static struct x509_certificate *
-certstore_found ( struct x509_certificate *cert ) {
+static void certstore_found ( struct x509_chain *store,
+ struct x509_certificate *cert ) {
/* Mark as most recently used */
list_del ( &cert->store.list );
- list_add ( &cert->store.list, &certstore.links );
- DBGC2 ( &certstore, "CERTSTORE found certificate %s\n",
+ list_add ( &cert->store.list, &store->links );
+ DBGC2 ( store, "CERTSTORE found certificate %s\n",
x509_name ( cert ) );
-
- return cert;
-}
-
-/**
- * Find certificate in store
- *
- * @v raw Raw certificate data
- * @ret cert X.509 certificate, or NULL if not found
- */
-struct x509_certificate * certstore_find ( struct asn1_cursor *raw ) {
- struct x509_certificate *cert;
-
- /* Search for certificate within store */
- list_for_each_entry ( cert, &certstore.links, store.list ) {
- if ( asn1_compare ( raw, &cert->raw ) == 0 )
- return certstore_found ( cert );
- }
- return NULL;
}
-/**
- * Find certificate in store corresponding to a private key
- *
- * @v key Private key
- * @ret cert X.509 certificate, or NULL if not found
- */
-struct x509_certificate * certstore_find_key ( struct private_key *key ) {
- struct x509_certificate *cert;
-
- /* Search for certificate within store */
- list_for_each_entry ( cert, &certstore.links, store.list ) {
- if ( pubkey_match ( cert->signature_algorithm->pubkey,
- key->builder.data, key->builder.len,
- cert->subject.public_key.raw.data,
- cert->subject.public_key.raw.len ) == 0 )
- return certstore_found ( cert );
- }
- return NULL;
-}
+/** Certificate store */
+struct x509_chain certstore = {
+ .refcnt = REF_INIT ( ref_no_free ),
+ .links = LIST_HEAD_INIT ( certstore.links ),
+ .found = certstore_found,
+};
/**
* Add certificate to store
@@ -219,7 +181,7 @@ static void certstore_init ( void ) {
/* Skip if certificate already present in store */
raw = &certstore_raw[i];
- if ( ( cert = certstore_find ( raw ) ) != NULL ) {
+ if ( ( cert = x509_find ( &certstore, raw ) ) != NULL ) {
DBGC ( &certstore, "CERTSTORE permanent certificate %d "
"is a duplicate of %s\n", i, x509_name ( cert ));
continue;
diff --git a/src/crypto/cms.c b/src/crypto/cms.c
index 9511cec..6c8217c 100644
--- a/src/crypto/cms.c
+++ b/src/crypto/cms.c
@@ -37,8 +37,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <errno.h>
#include <ipxe/asn1.h>
#include <ipxe/x509.h>
+#include <ipxe/image.h>
#include <ipxe/malloc.h>
#include <ipxe/uaccess.h>
+#include <ipxe/privkey.h>
#include <ipxe/cms.h>
/* Disambiguate the various error causes */
@@ -58,60 +60,109 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
__einfo_error ( EINFO_EACCES_NO_SIGNATURES )
#define EINFO_EACCES_NO_SIGNATURES \
__einfo_uniqify ( EINFO_EACCES, 0x05, "No signatures present" )
-#define EINVAL_DIGEST \
- __einfo_error ( EINFO_EINVAL_DIGEST )
-#define EINFO_EINVAL_DIGEST \
- __einfo_uniqify ( EINFO_EINVAL, 0x01, "Not a digest algorithm" )
-#define EINVAL_PUBKEY \
- __einfo_error ( EINFO_EINVAL_PUBKEY )
-#define EINFO_EINVAL_PUBKEY \
- __einfo_uniqify ( EINFO_EINVAL, 0x02, "Not a public-key algorithm" )
-#define ENOTSUP_SIGNEDDATA \
- __einfo_error ( EINFO_ENOTSUP_SIGNEDDATA )
-#define EINFO_ENOTSUP_SIGNEDDATA \
- __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Not a digital signature" )
-
-/** "pkcs7-signedData" object identifier */
+#define EACCES_NO_RECIPIENTS \
+ __einfo_error ( EINFO_EACCES_NO_RECIPIENTS )
+#define EINFO_EACCES_NO_RECIPIENTS \
+ __einfo_uniqify ( EINFO_EACCES, 0x06, "No usable recipients" )
+#define EACCES_LEN \
+ __einfo_error ( EINFO_EACCES_LEN )
+#define EINFO_EACCES_LEN \
+ __einfo_uniqify ( EINFO_EACCES, 0x07, "Bad file length" )
+#define EACCES_PAD \
+ __einfo_error ( EINFO_EACCES_PAD )
+#define EINFO_EACCES_PAD \
+ __einfo_uniqify ( EINFO_EACCES, 0x08, "Bad block padding" )
+#define EACCES_MAC \
+ __einfo_error ( EINFO_EACCES_MAC )
+#define EINFO_EACCES_MAC \
+ __einfo_uniqify ( EINFO_EACCES, 0x09, "Invalid MAC" )
+#define ENOTSUP_TYPE \
+ __einfo_error ( EINFO_ENOTSUP_TYPE )
+#define EINFO_ENOTSUP_TYPE \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unrecognised message type" )
+
+/** Buffer size for decryption
+ *
+ * Must be at least 256 to allow block padding to be removed if
+ * needed.
+ */
+#define CMS_DECRYPT_BLKSZ 2048
+
+static int cms_parse_signed ( struct cms_message *cms,
+ const struct asn1_cursor *raw );
+static int cms_parse_enveloped ( struct cms_message *cms,
+ const struct asn1_cursor *raw );
+
+/** "id-signedData" object identifier */
static uint8_t oid_signeddata[] = { ASN1_OID_SIGNEDDATA };
-/** "pkcs7-signedData" object identifier cursor */
-static struct asn1_cursor oid_signeddata_cursor =
- ASN1_CURSOR ( oid_signeddata );
+/** "id-envelopedData" object identifier */
+static uint8_t oid_envelopeddata[] = { ASN1_OID_ENVELOPEDDATA };
+
+/** "id-authEnvelopedData" object identifier */
+static uint8_t oid_authenvelopeddata[] = { ASN1_OID_AUTHENVELOPEDDATA };
+
+/** CMS message types */
+static struct cms_type cms_types[] = {
+ {
+ .name = "signed",
+ .oid = ASN1_CURSOR ( oid_signeddata ),
+ .parse = cms_parse_signed,
+ },
+ {
+ .name = "enveloped",
+ .oid = ASN1_CURSOR ( oid_envelopeddata ),
+ .parse = cms_parse_enveloped,
+ },
+ {
+ .name = "authEnveloped",
+ .oid = ASN1_CURSOR ( oid_authenvelopeddata ),
+ .parse = cms_parse_enveloped,
+ }
+};
/**
- * Parse CMS signature content type
+ * Parse CMS message content type
*
- * @v sig CMS signature
+ * @v cms CMS message
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
-static int cms_parse_content_type ( struct cms_signature *sig,
+static int cms_parse_content_type ( struct cms_message *cms,
const struct asn1_cursor *raw ) {
struct asn1_cursor cursor;
+ struct cms_type *type;
+ unsigned int i;
/* Enter contentType */
memcpy ( &cursor, raw, sizeof ( cursor ) );
asn1_enter ( &cursor, ASN1_OID );
- /* Check OID is pkcs7-signedData */
- if ( asn1_compare ( &cursor, &oid_signeddata_cursor ) != 0 ) {
- DBGC ( sig, "CMS %p does not contain signedData:\n", sig );
- DBGC_HDA ( sig, 0, raw->data, raw->len );
- return -ENOTSUP_SIGNEDDATA;
+ /* Check for a recognised OID */
+ for ( i = 0 ; i < ( sizeof ( cms_types ) /
+ sizeof ( cms_types[0] ) ) ; i++ ) {
+ type = &cms_types[i];
+ if ( asn1_compare ( &cursor, &type->oid ) == 0 ) {
+ cms->type = type;
+ DBGC ( cms, "CMS %p contains %sData\n",
+ cms, type->name );
+ return 0;
+ }
}
- DBGC ( sig, "CMS %p contains signedData\n", sig );
- return 0;
+ DBGC ( cms, "CMS %p is not a recognised message type:\n", cms );
+ DBGC_HDA ( cms, 0, raw->data, raw->len );
+ return -ENOTSUP_TYPE;
}
/**
- * Parse CMS signature certificate list
+ * Parse CMS message certificate list
*
- * @v sig CMS signature
+ * @v cms CMS message
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
-static int cms_parse_certificates ( struct cms_signature *sig,
+static int cms_parse_certificates ( struct cms_message *cms,
const struct asn1_cursor *raw ) {
struct asn1_cursor cursor;
struct x509_certificate *cert;
@@ -125,16 +176,16 @@ static int cms_parse_certificates ( struct cms_signature *sig,
while ( cursor.len ) {
/* Add certificate to chain */
- if ( ( rc = x509_append_raw ( sig->certificates, cursor.data,
+ if ( ( rc = x509_append_raw ( cms->certificates, cursor.data,
cursor.len ) ) != 0 ) {
- DBGC ( sig, "CMS %p could not append certificate: %s\n",
- sig, strerror ( rc) );
- DBGC_HDA ( sig, 0, cursor.data, cursor.len );
+ DBGC ( cms, "CMS %p could not append certificate: %s\n",
+ cms, strerror ( rc) );
+ DBGC_HDA ( cms, 0, cursor.data, cursor.len );
return rc;
}
- cert = x509_last ( sig->certificates );
- DBGC ( sig, "CMS %p found certificate %s\n",
- sig, x509_name ( cert ) );
+ cert = x509_last ( cms->certificates );
+ DBGC ( cms, "CMS %p found certificate %s\n",
+ cms, x509_name ( cert ) );
/* Move to next certificate */
asn1_skip_any ( &cursor );
@@ -144,44 +195,16 @@ static int cms_parse_certificates ( struct cms_signature *sig,
}
/**
- * Identify CMS signature certificate by issuer and serial number
- *
- * @v sig CMS signature
- * @v issuer Issuer
- * @v serial Serial number
- * @ret cert X.509 certificate, or NULL if not found
- */
-static struct x509_certificate *
-cms_find_issuer_serial ( struct cms_signature *sig,
- const struct asn1_cursor *issuer,
- const struct asn1_cursor *serial ) {
- struct x509_link *link;
- struct x509_certificate *cert;
-
- /* Scan through certificate list */
- list_for_each_entry ( link, &sig->certificates->links, list ) {
-
- /* Check issuer and serial number */
- cert = link->cert;
- if ( ( asn1_compare ( issuer, &cert->issuer.raw ) == 0 ) &&
- ( asn1_compare ( serial, &cert->serial.raw ) == 0 ) )
- return cert;
- }
-
- return NULL;
-}
-
-/**
- * Parse CMS signature signer identifier
+ * Parse CMS message participant identifier
*
- * @v sig CMS signature
- * @v info Signer information to fill in
+ * @v cms CMS message
+ * @v part Participant information to fill in
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
-static int cms_parse_signer_identifier ( struct cms_signature *sig,
- struct cms_signer_info *info,
- const struct asn1_cursor *raw ) {
+static int cms_parse_identifier ( struct cms_message *cms,
+ struct cms_participant *part,
+ const struct asn1_cursor *raw ) {
struct asn1_cursor cursor;
struct asn1_cursor serial;
struct asn1_cursor issuer;
@@ -195,46 +218,46 @@ static int cms_parse_signer_identifier ( struct cms_signature *sig,
/* Identify issuer */
memcpy ( &issuer, &cursor, sizeof ( issuer ) );
if ( ( rc = asn1_shrink ( &issuer, ASN1_SEQUENCE ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p could not locate issuer: %s\n",
- sig, info, strerror ( rc ) );
- DBGC_HDA ( sig, 0, raw->data, raw->len );
+ DBGC ( cms, "CMS %p/%p could not locate issuer: %s\n",
+ cms, part, strerror ( rc ) );
+ DBGC_HDA ( cms, 0, raw->data, raw->len );
return rc;
}
- DBGC ( sig, "CMS %p/%p issuer is:\n", sig, info );
- DBGC_HDA ( sig, 0, issuer.data, issuer.len );
+ DBGC ( cms, "CMS %p/%p issuer is:\n", cms, part );
+ DBGC_HDA ( cms, 0, issuer.data, issuer.len );
asn1_skip_any ( &cursor );
/* Identify serialNumber */
memcpy ( &serial, &cursor, sizeof ( serial ) );
if ( ( rc = asn1_shrink ( &serial, ASN1_INTEGER ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p could not locate serialNumber: %s\n",
- sig, info, strerror ( rc ) );
- DBGC_HDA ( sig, 0, raw->data, raw->len );
+ DBGC ( cms, "CMS %p/%p could not locate serialNumber: %s\n",
+ cms, part, strerror ( rc ) );
+ DBGC_HDA ( cms, 0, raw->data, raw->len );
return rc;
}
- DBGC ( sig, "CMS %p/%p serial number is:\n", sig, info );
- DBGC_HDA ( sig, 0, serial.data, serial.len );
+ DBGC ( cms, "CMS %p/%p serial number is:\n", cms, part );
+ DBGC_HDA ( cms, 0, serial.data, serial.len );
/* Identify certificate */
- cert = cms_find_issuer_serial ( sig, &issuer, &serial );
+ cert = x509_find_issuer_serial ( cms->certificates, &issuer, &serial );
if ( ! cert ) {
- DBGC ( sig, "CMS %p/%p could not identify signer's "
- "certificate\n", sig, info );
- return -ENOENT;
+ DBGC ( cms, "CMS %p/%p could not identify certificate\n",
+ cms, part );
+ return ( cms_is_signature ( cms ) ? -ENOENT : 0 );
}
/* Append certificate to chain */
- if ( ( rc = x509_append ( info->chain, cert ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p could not append certificate: %s\n",
- sig, info, strerror ( rc ) );
+ if ( ( rc = x509_append ( part->chain, cert ) ) != 0 ) {
+ DBGC ( cms, "CMS %p/%p could not append certificate: %s\n",
+ cms, part, strerror ( rc ) );
return rc;
}
/* Append remaining certificates to chain */
- if ( ( rc = x509_auto_append ( info->chain,
- sig->certificates ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p could not append certificates: %s\n",
- sig, info, strerror ( rc ) );
+ if ( ( rc = x509_auto_append ( part->chain,
+ cms->certificates ) ) != 0 ) {
+ DBGC ( cms, "CMS %p/%p could not append certificates: %s\n",
+ cms, part, strerror ( rc ) );
return rc;
}
@@ -242,173 +265,285 @@ static int cms_parse_signer_identifier ( struct cms_signature *sig,
}
/**
- * Parse CMS signature digest algorithm
+ * Parse CMS message digest algorithm
*
- * @v sig CMS signature
- * @v info Signer information to fill in
+ * @v cms CMS message
+ * @v part Participant information to fill in
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
-static int cms_parse_digest_algorithm ( struct cms_signature *sig,
- struct cms_signer_info *info,
+static int cms_parse_digest_algorithm ( struct cms_message *cms,
+ struct cms_participant *part,
const struct asn1_cursor *raw ) {
struct asn1_algorithm *algorithm;
int rc;
/* Identify algorithm */
if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p could not identify digest algorithm: "
- "%s\n", sig, info, strerror ( rc ) );
- DBGC_HDA ( sig, 0, raw->data, raw->len );
+ DBGC ( cms, "CMS %p/%p could not identify digest algorithm: "
+ "%s\n", cms, part, strerror ( rc ) );
+ DBGC_HDA ( cms, 0, raw->data, raw->len );
return rc;
}
/* Record digest algorithm */
- info->digest = algorithm->digest;
- DBGC ( sig, "CMS %p/%p digest algorithm is %s\n",
- sig, info, algorithm->name );
+ part->digest = algorithm->digest;
+ DBGC ( cms, "CMS %p/%p digest algorithm is %s\n",
+ cms, part, algorithm->name );
return 0;
}
/**
- * Parse CMS signature algorithm
+ * Parse CMS message public-key algorithm
*
- * @v sig CMS signature
- * @v info Signer information to fill in
+ * @v cms CMS message
+ * @v part Participant information to fill in
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
-static int cms_parse_signature_algorithm ( struct cms_signature *sig,
- struct cms_signer_info *info,
- const struct asn1_cursor *raw ) {
+static int cms_parse_pubkey_algorithm ( struct cms_message *cms,
+ struct cms_participant *part,
+ const struct asn1_cursor *raw ) {
struct asn1_algorithm *algorithm;
int rc;
/* Identify algorithm */
if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p could not identify public-key "
- "algorithm: %s\n", sig, info, strerror ( rc ) );
- DBGC_HDA ( sig, 0, raw->data, raw->len );
+ DBGC ( cms, "CMS %p/%p could not identify public-key "
+ "algorithm: %s\n", cms, part, strerror ( rc ) );
+ DBGC_HDA ( cms, 0, raw->data, raw->len );
return rc;
}
- /* Record signature algorithm */
- info->pubkey = algorithm->pubkey;
- DBGC ( sig, "CMS %p/%p public-key algorithm is %s\n",
- sig, info, algorithm->name );
+ /* Record public-key algorithm */
+ part->pubkey = algorithm->pubkey;
+ DBGC ( cms, "CMS %p/%p public-key algorithm is %s\n",
+ cms, part, algorithm->name );
return 0;
}
/**
- * Parse CMS signature value
+ * Parse CMS message cipher algorithm
*
- * @v sig CMS signature
- * @v info Signer information to fill in
+ * @v cms CMS message
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
-static int cms_parse_signature_value ( struct cms_signature *sig,
- struct cms_signer_info *info,
- const struct asn1_cursor *raw ) {
- struct asn1_cursor cursor;
+static int cms_parse_cipher_algorithm ( struct cms_message *cms,
+ const struct asn1_cursor *raw ) {
+ struct asn1_algorithm *algorithm;
int rc;
- /* Enter signature */
- memcpy ( &cursor, raw, sizeof ( cursor ) );
- if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p could not locate signature:\n",
- sig, info );
- DBGC_HDA ( sig, 0, raw->data, raw->len );
+ /* Identify algorithm */
+ if ( ( rc = asn1_cipher_algorithm ( raw, &algorithm,
+ &cms->iv ) ) != 0 ) {
+ DBGC ( cms, "CMS %p could not identify cipher algorithm: %s\n",
+ cms, strerror ( rc ) );
+ DBGC_HDA ( cms, 0, raw->data, raw->len );
return rc;
}
- /* Record signature */
- info->signature_len = cursor.len;
- info->signature = malloc ( info->signature_len );
- if ( ! info->signature )
- return -ENOMEM;
- memcpy ( info->signature, cursor.data, info->signature_len );
- DBGC ( sig, "CMS %p/%p signature value is:\n", sig, info );
- DBGC_HDA ( sig, 0, info->signature, info->signature_len );
+ /* Record cipher */
+ cms->cipher = algorithm->cipher;
+ DBGC ( cms, "CMS %p cipher algorithm is %s\n", cms, algorithm->name );
return 0;
}
/**
- * Parse CMS signature signer information
+ * Parse CMS message signature or key value
*
- * @v sig CMS signature
- * @v info Signer information to fill in
+ * @v cms CMS message
+ * @v part Participant information to fill in
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
-static int cms_parse_signer_info ( struct cms_signature *sig,
- struct cms_signer_info *info,
+static int cms_parse_value ( struct cms_message *cms,
+ struct cms_participant *part,
+ const struct asn1_cursor *raw ) {
+ int rc;
+
+ /* Enter signature or encryptedKey */
+ memcpy ( &part->value, raw, sizeof ( part->value ) );
+ if ( ( rc = asn1_enter ( &part->value, ASN1_OCTET_STRING ) ) != 0 ) {
+ DBGC ( cms, "CMS %p/%p could not locate value:\n",
+ cms, part );
+ DBGC_HDA ( cms, 0, raw->data, raw->len );
+ return rc;
+ }
+ DBGC ( cms, "CMS %p/%p value is:\n", cms, part );
+ DBGC_HDA ( cms, 0, part->value.data, part->value.len );
+
+ return 0;
+}
+
+/**
+ * Parse CMS message participant information
+ *
+ * @v cms CMS message
+ * @v part Participant information to fill in
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_participant ( struct cms_message *cms,
+ struct cms_participant *part,
const struct asn1_cursor *raw ) {
struct asn1_cursor cursor;
int rc;
- /* Enter signerInfo */
+ /* Enter signerInfo or ktri */
memcpy ( &cursor, raw, sizeof ( cursor ) );
asn1_enter ( &cursor, ASN1_SEQUENCE );
/* Skip version */
asn1_skip ( &cursor, ASN1_INTEGER );
- /* Parse sid */
- if ( ( rc = cms_parse_signer_identifier ( sig, info, &cursor ) ) != 0 )
+ /* Parse sid or rid */
+ if ( ( rc = cms_parse_identifier ( cms, part, &cursor ) ) != 0 )
return rc;
asn1_skip_any ( &cursor );
- /* Parse digestAlgorithm */
- if ( ( rc = cms_parse_digest_algorithm ( sig, info, &cursor ) ) != 0 )
- return rc;
- asn1_skip_any ( &cursor );
+ /* Parse signature-only objects */
+ if ( cms_is_signature ( cms ) ) {
- /* Skip signedAttrs, if present */
- asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+ /* Parse digestAlgorithm */
+ if ( ( rc = cms_parse_digest_algorithm ( cms, part,
+ &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Skip signedAttrs, if present */
+ asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+ }
- /* Parse signatureAlgorithm */
- if ( ( rc = cms_parse_signature_algorithm ( sig, info, &cursor ) ) != 0)
+ /* Parse signatureAlgorithm or contentEncryptionAlgorithm */
+ if ( ( rc = cms_parse_pubkey_algorithm ( cms, part, &cursor ) ) != 0 )
return rc;
asn1_skip_any ( &cursor );
- /* Parse signature */
- if ( ( rc = cms_parse_signature_value ( sig, info, &cursor ) ) != 0 )
+ /* Parse signature or encryptedKey */
+ if ( ( rc = cms_parse_value ( cms, part, &cursor ) ) != 0 )
return rc;
return 0;
}
/**
- * Parse CMS signature from ASN.1 data
+ * Parse CMS message participants information
*
- * @v sig CMS signature
+ * @v cms CMS message
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
-static int cms_parse ( struct cms_signature *sig,
- const struct asn1_cursor *raw ) {
+static int cms_parse_participants ( struct cms_message *cms,
+ const struct asn1_cursor *raw ) {
struct asn1_cursor cursor;
- struct cms_signer_info *info;
+ struct cms_participant *part;
int rc;
- /* Enter contentInfo */
+ /* Enter signerInfos or recipientInfos */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SET );
+
+ /* Add each signerInfo or recipientInfo. Errors are handled
+ * by ensuring that cms_put() will always be able to free any
+ * allocated memory.
+ */
+ while ( cursor.len ) {
+
+ /* Allocate participant information block */
+ part = zalloc ( sizeof ( *part ) );
+ if ( ! part )
+ return -ENOMEM;
+ list_add ( &part->list, &cms->participants );
+
+ /* Allocate certificate chain */
+ part->chain = x509_alloc_chain();
+ if ( ! part->chain )
+ return -ENOMEM;
+
+ /* Parse signerInfo or recipientInfo */
+ if ( ( rc = cms_parse_participant ( cms, part,
+ &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+ }
+
+ return 0;
+}
+
+/**
+ * Parse CMS message encrypted content information
+ *
+ * @v cms CMS message
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_encrypted ( struct cms_message *cms,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter encryptedContentInfo */
memcpy ( &cursor, raw, sizeof ( cursor ) );
asn1_enter ( &cursor, ASN1_SEQUENCE );
- /* Parse contentType */
+ /* Skip contentType */
+ asn1_skip ( &cursor, ASN1_OID );
- if ( ( rc = cms_parse_content_type ( sig, &cursor ) ) != 0 )
+ /* Parse contentEncryptionAlgorithm */
+ if ( ( rc = cms_parse_cipher_algorithm ( cms, &cursor ) ) != 0 )
return rc;
- asn1_skip_any ( &cursor );
- /* Enter content */
- asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+ return 0;
+}
+
+/**
+ * Parse CMS message MAC
+ *
+ * @v cms CMS message
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_mac ( struct cms_message *cms,
+ const struct asn1_cursor *raw ) {
+ int rc;
+
+ /* Enter mac */
+ memcpy ( &cms->mac, raw, sizeof ( cms->mac ) );
+ if ( ( rc = asn1_enter ( &cms->mac, ASN1_OCTET_STRING ) ) != 0 ) {
+ DBGC ( cms, "CMS %p could not locate mac: %s\n",
+ cms, strerror ( rc ) );
+ DBGC_HDA ( cms, 0, raw->data, raw->len );
+ return rc;
+ }
+ DBGC ( cms, "CMS %p mac is:\n", cms );
+ DBGC_HDA ( cms, 0, cms->mac.data, cms->mac.len );
+
+ return 0;
+}
+
+/**
+ * Parse CMS signed data
+ *
+ * @v cms CMS message
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_signed ( struct cms_message *cms,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Allocate certificate list */
+ cms->certificates = x509_alloc_chain();
+ if ( ! cms->certificates )
+ return -ENOMEM;
/* Enter signedData */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
asn1_enter ( &cursor, ASN1_SEQUENCE );
/* Skip version */
@@ -421,108 +556,159 @@ static int cms_parse ( struct cms_signature *sig,
asn1_skip ( &cursor, ASN1_SEQUENCE );
/* Parse certificates */
- if ( ( rc = cms_parse_certificates ( sig, &cursor ) ) != 0 )
+ if ( ( rc = cms_parse_certificates ( cms, &cursor ) ) != 0 )
return rc;
asn1_skip_any ( &cursor );
/* Skip crls, if present */
asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) );
- /* Enter signerInfos */
- asn1_enter ( &cursor, ASN1_SET );
+ /* Parse signerInfos */
+ if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
+ return rc;
- /* Add each signerInfo. Errors are handled by ensuring that
- * cms_put() will always be able to free any allocated memory.
- */
- while ( cursor.len ) {
+ return 0;
+}
- /* Allocate signer information block */
- info = zalloc ( sizeof ( *info ) );
- if ( ! info )
- return -ENOMEM;
- list_add ( &info->list, &sig->info );
+/**
+ * Parse CMS enveloped data
+ *
+ * @v cms CMS message
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+static int cms_parse_enveloped ( struct cms_message *cms,
+ const struct asn1_cursor *raw ) {
+ struct asn1_cursor cursor;
+ int rc;
- /* Allocate certificate chain */
- info->chain = x509_alloc_chain();
- if ( ! info->chain )
- return -ENOMEM;
+ /* Enter envelopedData or authEnvelopedData */
+ memcpy ( &cursor, raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
- /* Parse signerInfo */
- if ( ( rc = cms_parse_signer_info ( sig, info,
- &cursor ) ) != 0 )
- return rc;
- asn1_skip_any ( &cursor );
- }
+ /* Skip version */
+ asn1_skip ( &cursor, ASN1_INTEGER );
+
+ /* Skip originatorInfo, if present */
+ asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 0 ) );
+
+ /* Parse recipientInfos */
+ if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Parse encryptedContentInfo or authEncryptedContentInfo */
+ if ( ( rc = cms_parse_encrypted ( cms, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+ assert ( cms->cipher != NULL );
+
+ /* Skip unprotectedAttrs or authAttrs, if present */
+ asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 1 ) );
+
+ /* Parse mac, if present */
+ if ( ( cms->cipher->authsize != 0 ) &&
+ ( ( rc = cms_parse_mac ( cms, &cursor ) ) != 0 ) )
+ return rc;
return 0;
}
/**
- * Free CMS signature
+ * Parse CMS message from ASN.1 data
+ *
+ * @v cms CMS message
+ * @ret rc Return status code
+ */
+static int cms_parse ( struct cms_message *cms ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Enter contentInfo */
+ memcpy ( &cursor, cms->raw, sizeof ( cursor ) );
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Parse contentType */
+ if ( ( rc = cms_parse_content_type ( cms, &cursor ) ) != 0 )
+ return rc;
+ asn1_skip_any ( &cursor );
+
+ /* Enter content */
+ asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
+
+ /* Parse type-specific content */
+ if ( ( rc = cms->type->parse ( cms, &cursor ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Free CMS message
*
* @v refcnt Reference count
*/
static void cms_free ( struct refcnt *refcnt ) {
- struct cms_signature *sig =
- container_of ( refcnt, struct cms_signature, refcnt );
- struct cms_signer_info *info;
- struct cms_signer_info *tmp;
-
- list_for_each_entry_safe ( info, tmp, &sig->info, list ) {
- list_del ( &info->list );
- x509_chain_put ( info->chain );
- free ( info->signature );
- free ( info );
- }
- x509_chain_put ( sig->certificates );
- free ( sig );
+ struct cms_message *cms =
+ container_of ( refcnt, struct cms_message, refcnt );
+ struct cms_participant *part;
+ struct cms_participant *tmp;
+
+ list_for_each_entry_safe ( part, tmp, &cms->participants, list ) {
+ list_del ( &part->list );
+ x509_chain_put ( part->chain );
+ free ( part );
+ }
+ x509_chain_put ( cms->certificates );
+ free ( cms->raw );
+ free ( cms );
}
/**
- * Create CMS signature
+ * Create CMS message
*
- * @v data Raw signature data
- * @v len Length of raw data
- * @ret sig CMS signature
+ * @v image Image
+ * @ret sig CMS message
* @ret rc Return status code
*
- * On success, the caller holds a reference to the CMS signature, and
+ * On success, the caller holds a reference to the CMS message, and
* is responsible for ultimately calling cms_put().
*/
-int cms_signature ( const void *data, size_t len, struct cms_signature **sig ) {
- struct asn1_cursor cursor;
+int cms_message ( struct image *image, struct cms_message **cms ) {
+ int next;
int rc;
- /* Allocate and initialise signature */
- *sig = zalloc ( sizeof ( **sig ) );
- if ( ! *sig ) {
+ /* Allocate and initialise message */
+ *cms = zalloc ( sizeof ( **cms ) );
+ if ( ! *cms ) {
rc = -ENOMEM;
goto err_alloc;
}
- ref_init ( &(*sig)->refcnt, cms_free );
- INIT_LIST_HEAD ( &(*sig)->info );
-
- /* Allocate certificate list */
- (*sig)->certificates = x509_alloc_chain();
- if ( ! (*sig)->certificates ) {
- rc = -ENOMEM;
- goto err_alloc_chain;
+ ref_init ( &(*cms)->refcnt, cms_free );
+ INIT_LIST_HEAD ( &(*cms)->participants );
+ (*cms)->cipher = &cipher_null;
+
+ /* Get raw message data */
+ next = image_asn1 ( image, 0, &(*cms)->raw );
+ if ( next < 0 ) {
+ rc = next;
+ DBGC ( *cms, "CMS %p could not get raw ASN.1 data: %s\n",
+ *cms, strerror ( rc ) );
+ goto err_asn1;
}
- /* Initialise cursor */
- cursor.data = data;
- cursor.len = len;
- asn1_shrink_any ( &cursor );
+ /* Use only first message in image */
+ asn1_shrink_any ( (*cms)->raw );
- /* Parse signature */
- if ( ( rc = cms_parse ( *sig, &cursor ) ) != 0 )
+ /* Parse message */
+ if ( ( rc = cms_parse ( *cms ) ) != 0 )
goto err_parse;
return 0;
err_parse:
- err_alloc_chain:
- cms_put ( *sig );
+ err_asn1:
+ cms_put ( *cms );
err_alloc:
return rc;
}
@@ -530,16 +716,16 @@ int cms_signature ( const void *data, size_t len, struct cms_signature **sig ) {
/**
* Calculate digest of CMS-signed data
*
- * @v sig CMS signature
- * @v info Signer information
+ * @v cms CMS message
+ * @v part Participant information
* @v data Signed data
* @v len Length of signed data
* @v out Digest output
*/
-static void cms_digest ( struct cms_signature *sig,
- struct cms_signer_info *info,
+static void cms_digest ( struct cms_message *cms,
+ struct cms_participant *part,
userptr_t data, size_t len, void *out ) {
- struct digest_algorithm *digest = info->digest;
+ struct digest_algorithm *digest = part->digest;
uint8_t ctx[ digest->ctxsize ];
uint8_t block[ digest->blocksize ];
size_t offset = 0;
@@ -562,62 +748,50 @@ static void cms_digest ( struct cms_signature *sig,
/* Finalise digest */
digest_final ( digest, ctx, out );
- DBGC ( sig, "CMS %p/%p digest value:\n", sig, info );
- DBGC_HDA ( sig, 0, out, digest->digestsize );
+ DBGC ( cms, "CMS %p/%p digest value:\n", cms, part );
+ DBGC_HDA ( cms, 0, out, digest->digestsize );
}
/**
* Verify digest of CMS-signed data
*
- * @v sig CMS signature
- * @v info Signer information
+ * @v cms CMS message
+ * @v part Participant information
* @v cert Corresponding certificate
* @v data Signed data
* @v len Length of signed data
* @ret rc Return status code
*/
-static int cms_verify_digest ( struct cms_signature *sig,
- struct cms_signer_info *info,
+static int cms_verify_digest ( struct cms_message *cms,
+ struct cms_participant *part,
struct x509_certificate *cert,
userptr_t data, size_t len ) {
- struct digest_algorithm *digest = info->digest;
- struct pubkey_algorithm *pubkey = info->pubkey;
- struct x509_public_key *public_key = &cert->subject.public_key;
+ struct digest_algorithm *digest = part->digest;
+ struct pubkey_algorithm *pubkey = part->pubkey;
+ const struct asn1_cursor *key = &cert->subject.public_key.raw;
+ const struct asn1_cursor *value = &part->value;
uint8_t digest_out[ digest->digestsize ];
- uint8_t ctx[ pubkey->ctxsize ];
int rc;
/* Generate digest */
- cms_digest ( sig, info, data, len, digest_out );
-
- /* Initialise public-key algorithm */
- if ( ( rc = pubkey_init ( pubkey, ctx, public_key->raw.data,
- public_key->raw.len ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p could not initialise public key: %s\n",
- sig, info, strerror ( rc ) );
- goto err_init;
- }
+ cms_digest ( cms, part, data, len, digest_out );
/* Verify digest */
- if ( ( rc = pubkey_verify ( pubkey, ctx, digest, digest_out,
- info->signature,
- info->signature_len ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p signature verification failed: %s\n",
- sig, info, strerror ( rc ) );
- goto err_verify;
+ if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
+ value->data, value->len ) ) != 0 ) {
+ DBGC ( cms, "CMS %p/%p signature verification failed: %s\n",
+ cms, part, strerror ( rc ) );
+ return rc;
}
- err_verify:
- pubkey_final ( pubkey, ctx );
- err_init:
- return rc;
+ return 0;
}
/**
- * Verify CMS signature signer information
+ * Verify CMS message signer
*
- * @v sig CMS signature
- * @v info Signer information
+ * @v cms CMS message
+ * @v part Participant information
* @v data Signed data
* @v len Length of signed data
* @v time Time at which to validate certificates
@@ -625,42 +799,42 @@ static int cms_verify_digest ( struct cms_signature *sig,
* @v root Root certificate list, or NULL to use default
* @ret rc Return status code
*/
-static int cms_verify_signer_info ( struct cms_signature *sig,
- struct cms_signer_info *info,
- userptr_t data, size_t len,
- time_t time, struct x509_chain *store,
- struct x509_root *root ) {
+static int cms_verify_signer ( struct cms_message *cms,
+ struct cms_participant *part,
+ userptr_t data, size_t len,
+ time_t time, struct x509_chain *store,
+ struct x509_root *root ) {
struct x509_certificate *cert;
int rc;
/* Validate certificate chain */
- if ( ( rc = x509_validate_chain ( info->chain, time, store,
+ if ( ( rc = x509_validate_chain ( part->chain, time, store,
root ) ) != 0 ) {
- DBGC ( sig, "CMS %p/%p could not validate chain: %s\n",
- sig, info, strerror ( rc ) );
+ DBGC ( cms, "CMS %p/%p could not validate chain: %s\n",
+ cms, part, strerror ( rc ) );
return rc;
}
/* Extract code-signing certificate */
- cert = x509_first ( info->chain );
+ cert = x509_first ( part->chain );
assert ( cert != NULL );
/* Check that certificate can create digital signatures */
if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) {
- DBGC ( sig, "CMS %p/%p certificate cannot create signatures\n",
- sig, info );
+ DBGC ( cms, "CMS %p/%p certificate cannot create signatures\n",
+ cms, part );
return -EACCES_NON_SIGNING;
}
/* Check that certificate can sign code */
if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) {
- DBGC ( sig, "CMS %p/%p certificate is not code-signing\n",
- sig, info );
+ DBGC ( cms, "CMS %p/%p certificate is not code-signing\n",
+ cms, part );
return -EACCES_NON_CODE_SIGNING;
}
/* Verify digest */
- if ( ( rc = cms_verify_digest ( sig, info, cert, data, len ) ) != 0 )
+ if ( ( rc = cms_verify_digest ( cms, part, cert, data, len ) ) != 0 )
return rc;
return 0;
@@ -669,30 +843,37 @@ static int cms_verify_signer_info ( struct cms_signature *sig,
/**
* Verify CMS signature
*
- * @v sig CMS signature
- * @v data Signed data
- * @v len Length of signed data
+ * @v cms CMS message
+ * @v image Signed image
* @v name Required common name, or NULL to check all signatures
* @v time Time at which to validate certificates
* @v store Certificate store, or NULL to use default
* @v root Root certificate list, or NULL to use default
* @ret rc Return status code
*/
-int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
+int cms_verify ( struct cms_message *cms, struct image *image,
const char *name, time_t time, struct x509_chain *store,
struct x509_root *root ) {
- struct cms_signer_info *info;
+ struct cms_participant *part;
struct x509_certificate *cert;
int count = 0;
int rc;
- /* Verify using all signerInfos */
- list_for_each_entry ( info, &sig->info, list ) {
- cert = x509_first ( info->chain );
+ /* Mark image as untrusted */
+ image_untrust ( image );
+
+ /* Sanity check */
+ if ( ! cms_is_signature ( cms ) )
+ return -ENOTTY;
+
+ /* Verify using all signers */
+ list_for_each_entry ( part, &cms->participants, list ) {
+ cert = x509_first ( part->chain );
if ( name && ( x509_check_name ( cert, name ) != 0 ) )
continue;
- if ( ( rc = cms_verify_signer_info ( sig, info, data, len, time,
- store, root ) ) != 0 )
+ if ( ( rc = cms_verify_signer ( cms, part, image->data,
+ image->len, time, store,
+ root ) ) != 0 )
return rc;
count++;
}
@@ -700,14 +881,329 @@ int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
/* Check that we have verified at least one signature */
if ( count == 0 ) {
if ( name ) {
- DBGC ( sig, "CMS %p had no signatures matching name "
- "%s\n", sig, name );
+ DBGC ( cms, "CMS %p had no signatures matching name "
+ "%s\n", cms, name );
return -EACCES_WRONG_NAME;
} else {
- DBGC ( sig, "CMS %p had no signatures\n", sig );
+ DBGC ( cms, "CMS %p had no signatures\n", cms );
return -EACCES_NO_SIGNATURES;
}
}
+ /* Mark image as trusted */
+ image_trust ( image );
+
+ return 0;
+}
+
+/**
+ * Identify CMS recipient corresponding to private key
+ *
+ * @v cms CMS message
+ * @v private_key Private key
+ * @ret part Participant information, or NULL if not found
+ */
+static struct cms_participant *
+cms_recipient ( struct cms_message *cms, struct private_key *private_key ) {
+ struct cms_participant *part;
+ struct x509_certificate *cert;
+
+ /* Identify certificate (if any) for which we have a private key */
+ cert = x509_find_key ( NULL, private_key );
+ if ( ! cert )
+ return NULL;
+
+ /* Identify corresponding recipient, if any */
+ list_for_each_entry ( part, &cms->participants, list ) {
+ if ( cert == x509_first ( part->chain ) )
+ return part;
+ }
+
+ return NULL;
+}
+
+/**
+ * Set CMS cipher key
+ *
+ * @v cms CMS message
+ * @v part Participant information
+ * @v private_key Private key
+ * @v ctx Cipher context
+ * @ret rc Return status code
+ */
+static int cms_cipher_key ( struct cms_message *cms,
+ struct cms_participant *part,
+ struct private_key *private_key, void *ctx ) {
+ struct cipher_algorithm *cipher = cms->cipher;
+ struct pubkey_algorithm *pubkey = part->pubkey;
+ const struct asn1_cursor *key = privkey_cursor ( private_key );
+ const struct asn1_cursor *value = &part->value;
+ size_t max_len = pubkey_max_len ( pubkey, key );
+ uint8_t cipher_key[max_len];
+ int len;
+ int rc;
+
+ /* Decrypt cipher key */
+ len = pubkey_decrypt ( pubkey, key, value->data, value->len,
+ cipher_key );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( cms, "CMS %p/%p could not decrypt cipher key: %s\n",
+ cms, part, strerror ( rc ) );
+ DBGC_HDA ( cms, 0, value->data, value->len );
+ return rc;
+ }
+ DBGC ( cms, "CMS %p/%p cipher key:\n", cms, part );
+ DBGC_HDA ( cms, 0, cipher_key, len );
+
+ /* Set cipher key */
+ if ( ( rc = cipher_setkey ( cipher, ctx, cipher_key, len ) ) != 0 ) {
+ DBGC ( cms, "CMS %p could not set cipher key: %s\n",
+ cms, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Set cipher initialization vector */
+ cipher_setiv ( cipher, ctx, cms->iv.data, cms->iv.len );
+ if ( cms->iv.len ) {
+ DBGC ( cms, "CMS %p cipher IV:\n", cms );
+ DBGC_HDA ( cms, 0, cms->iv.data, cms->iv.len );
+ }
+
return 0;
}
+
+/**
+ * Initialise cipher for CMS decryption
+ *
+ * @v cms CMS message
+ * @v private_key Private key
+ * @v ctx Cipher context
+ * @ret rc Return status code
+ */
+static int cms_cipher ( struct cms_message *cms,
+ struct private_key *private_key, void *ctx ) {
+ struct cms_participant *part;
+ int rc;
+
+ /* Identify a usable recipient */
+ part = cms_recipient ( cms, private_key );
+ if ( ! part ) {
+ DBGC ( cms, "CMS %p had no usable recipients\n", cms );
+ return -EACCES_NO_RECIPIENTS;
+ }
+
+ /* Decrypt and set cipher key */
+ if ( ( rc = cms_cipher_key ( cms, part, private_key, ctx ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Check CMS padding
+ *
+ * @v cms CMS message
+ * @v data Final block
+ * @v len Final block length
+ * @ret len Padding length, or negative error
+ */
+static int cms_verify_padding ( struct cms_message *cms, const void *data,
+ size_t len ) {
+ struct cipher_algorithm *cipher = cms->cipher;
+ const uint8_t *pad;
+ size_t pad_len;
+ unsigned int i;
+
+ /* Non-block ciphers do not use padding */
+ if ( ! is_block_cipher ( cipher ) )
+ return 0;
+
+ /* Block padding can never produce an empty file */
+ if ( len == 0 ) {
+ DBGC ( cms, "CMS %p invalid empty padding\n", cms );
+ return -EACCES_PAD;
+ }
+
+ /* Sanity check */
+ assert ( len >= cipher->blocksize );
+
+ /* Extract and verify padding */
+ pad = ( data + len - 1 );
+ pad_len = *pad;
+ if ( ( pad_len == 0 ) || ( pad_len > len ) ) {
+ DBGC ( cms, "CMS %p invalid padding length %zd\n",
+ cms, pad_len );
+ return -EACCES_PAD;
+ }
+ for ( i = 0 ; i < pad_len ; i++ ) {
+ if ( *(pad--) != pad_len ) {
+ DBGC ( cms, "CMS %p invalid padding\n", cms );
+ DBGC_HDA ( cms, 0, ( data + len - pad_len ), pad_len );
+ return -EACCES_PAD;
+ }
+ }
+
+ return pad_len;
+}
+
+/**
+ * Decrypt CMS message
+ *
+ * @v cms CMS message
+ * @v image Image to decrypt
+ * @v name Decrypted image name, or NULL to use default
+ * @v private_key Private key
+ * @ret rc Return status code
+ */
+int cms_decrypt ( struct cms_message *cms, struct image *image,
+ const char *name, struct private_key *private_key ) {
+ struct cipher_algorithm *cipher = cms->cipher;
+ const unsigned int original_flags = image->flags;
+ size_t offset;
+ size_t remaining;
+ size_t frag_len;
+ int pad_len;
+ void *tmp;
+ void *ctx;
+ void *ctxdup;
+ void *auth;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! cipher ) {
+ rc = -ENOTTY;
+ goto err_no_cipher;
+ }
+
+ /* Check block size */
+ if ( ( image->len & ( cipher->blocksize - 1 ) ) != 0 ) {
+ DBGC ( cms, "CMS %p invalid length %zd\n", cms, image->len );
+ rc = -EACCES_LEN;
+ goto err_blocksize;
+ }
+
+ /* Allocate temporary working space */
+ tmp = malloc ( CMS_DECRYPT_BLKSZ + ( 2 * cipher->ctxsize ) +
+ cipher->authsize );
+ if ( ! tmp ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ ctx = ( tmp + CMS_DECRYPT_BLKSZ );
+ ctxdup = ( ctx + cipher->ctxsize );
+ auth = ( ctxdup + cipher->ctxsize );
+
+ /* Initialise cipher */
+ if ( ( rc = cms_cipher ( cms, private_key, ctx ) ) != 0 )
+ goto err_cipher;
+
+ /* Duplicate cipher context for potential reencryption on error */
+ memcpy ( ctxdup, ctx, cipher->ctxsize );
+
+ /* Clear trusted flag before modifying image */
+ image_untrust ( image );
+
+ /* Temporarily unregister image, if applicable */
+ if ( original_flags & IMAGE_REGISTERED ) {
+ image_get ( image );
+ unregister_image ( image );
+ }
+
+ /* Decrypt one block at a time */
+ offset = 0;
+ remaining = image->len;
+ frag_len = 0;
+ while ( remaining ) {
+
+ /* Calculate fragment length */
+ frag_len = remaining;
+ if ( frag_len > CMS_DECRYPT_BLKSZ )
+ frag_len = CMS_DECRYPT_BLKSZ;
+
+ /* Decrypt fragment */
+ copy_from_user ( tmp, image->data, offset, frag_len );
+ cipher_decrypt ( cipher, ctx, tmp, tmp, frag_len );
+
+ /* Overwrite all but the final fragment */
+ if ( remaining > frag_len )
+ copy_to_user ( image->data, offset, tmp, frag_len );
+
+ /* Move to next block */
+ remaining -= frag_len;
+ offset += frag_len;
+ }
+
+ /* Check authentication tag, if applicable */
+ cipher_auth ( cipher, ctx, auth );
+ if ( ( cms->mac.len != cipher->authsize ) ||
+ ( memcmp ( cms->mac.data, auth, cipher->authsize ) != 0 ) ) {
+ DBGC ( cms, "CMS %p invalid authentication tag\n", cms );
+ DBGC_HDA ( cms, 0, auth, cipher->authsize );
+ rc = -EACCES_MAC;
+ goto err_auth;
+ }
+
+ /* Check block padding, if applicable */
+ if ( ( pad_len = cms_verify_padding ( cms, tmp, frag_len ) ) < 0 ) {
+ rc = pad_len;
+ goto err_pad;
+ }
+
+ /* Update image name. Do this as the last possible failure, so
+ * that we do not have to include any error-handling code path
+ * to restore the original image name (which may itself fail).
+ */
+ if ( name ) {
+ if ( ( rc = image_set_name ( image, name ) ) != 0 )
+ goto err_set_name;
+ } else {
+ image_strip_suffix ( image );
+ }
+
+ /* Overwrite final fragment and strip block padding. Do this
+ * only once no further failure paths exist, so that we do not
+ * have to include include any error-handling code path to
+ * reconstruct the block padding.
+ */
+ copy_to_user ( image->data, ( offset - frag_len ), tmp, frag_len );
+ image->len -= pad_len;
+
+ /* Clear image type and re-register image, if applicable */
+ image->type = NULL;
+ if ( original_flags & IMAGE_REGISTERED ) {
+ register_image ( image );
+ image_put ( image );
+ }
+
+ /* Free temporary working space */
+ free ( tmp );
+
+ return 0;
+
+ err_set_name:
+ err_pad:
+ err_auth:
+ /* Reencrypt all overwritten fragments. This can be done
+ * since we have deliberately not overwritten the final
+ * fragment containing the potentially invalid (and therefore
+ * unreproducible) block padding.
+ */
+ remaining = ( offset - frag_len );
+ for ( offset = 0 ; offset < remaining ; offset += CMS_DECRYPT_BLKSZ ) {
+ copy_from_user ( tmp, image->data, offset, CMS_DECRYPT_BLKSZ );
+ cipher_encrypt ( cipher, ctxdup, tmp, tmp, CMS_DECRYPT_BLKSZ );
+ copy_to_user ( image->data, offset, tmp, CMS_DECRYPT_BLKSZ );
+ }
+ if ( original_flags & IMAGE_REGISTERED ) {
+ register_image ( image ); /* Cannot fail on re-registration */
+ image_put ( image );
+ }
+ image->flags = original_flags;
+ err_cipher:
+ free ( tmp );
+ err_alloc:
+ err_blocksize:
+ err_no_cipher:
+ return rc;
+}
diff --git a/src/crypto/crypto_null.c b/src/crypto/crypto_null.c
index 0ad463c..d5863f9 100644
--- a/src/crypto/crypto_null.c
+++ b/src/crypto/crypto_null.c
@@ -93,34 +93,31 @@ struct cipher_algorithm cipher_null = {
.auth = cipher_null_auth,
};
-int pubkey_null_init ( void *ctx __unused, const void *key __unused,
- size_t key_len __unused ) {
+size_t pubkey_null_max_len ( const struct asn1_cursor *key __unused ) {
return 0;
}
-size_t pubkey_null_max_len ( void *ctx __unused ) {
- return 0;
-}
-
-int pubkey_null_encrypt ( void *ctx __unused, const void *plaintext __unused,
+int pubkey_null_encrypt ( const struct asn1_cursor *key __unused,
+ const void *plaintext __unused,
size_t plaintext_len __unused,
void *ciphertext __unused ) {
return 0;
}
-int pubkey_null_decrypt ( void *ctx __unused, const void *ciphertext __unused,
+int pubkey_null_decrypt ( const struct asn1_cursor *key __unused,
+ const void *ciphertext __unused,
size_t ciphertext_len __unused,
void *plaintext __unused ) {
return 0;
}
-int pubkey_null_sign ( void *ctx __unused,
+int pubkey_null_sign ( const struct asn1_cursor *key __unused,
struct digest_algorithm *digest __unused,
const void *value __unused, void *signature __unused ) {
return 0;
}
-int pubkey_null_verify ( void *ctx __unused,
+int pubkey_null_verify ( const struct asn1_cursor *key __unused,
struct digest_algorithm *digest __unused,
const void *value __unused,
const void *signature __unused ,
@@ -128,18 +125,11 @@ int pubkey_null_verify ( void *ctx __unused,
return 0;
}
-void pubkey_null_final ( void *ctx __unused ) {
- /* Do nothing */
-}
-
struct pubkey_algorithm pubkey_null = {
.name = "null",
- .ctxsize = 0,
- .init = pubkey_null_init,
.max_len = pubkey_null_max_len,
.encrypt = pubkey_null_encrypt,
.decrypt = pubkey_null_decrypt,
.sign = pubkey_null_sign,
.verify = pubkey_null_verify,
- .final = pubkey_null_final,
};
diff --git a/src/crypto/mishmash/oid_aes_cbc.c b/src/crypto/mishmash/oid_aes_cbc.c
new file mode 100644
index 0000000..b5f7165
--- /dev/null
+++ b/src/crypto/mishmash/oid_aes_cbc.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/aes.h>
+#include <ipxe/asn1.h>
+
+/** "aes128-cbc" object identifier */
+static uint8_t oid_aes_128_cbc[] = { ASN1_OID_AES128_CBC };
+
+/** "aes192-cbc" object identifier */
+static uint8_t oid_aes_192_cbc[] = { ASN1_OID_AES192_CBC };
+
+/** "aes256-cbc" object identifier */
+static uint8_t oid_aes_256_cbc[] = { ASN1_OID_AES256_CBC };
+
+/** "aes128-cbc" OID-identified algorithm */
+struct asn1_algorithm aes_128_cbc_algorithm __asn1_algorithm = {
+ .name = "aes128-cbc",
+ .cipher = &aes_cbc_algorithm,
+ .oid = ASN1_CURSOR ( oid_aes_128_cbc ),
+ .parse = asn1_parse_cbc,
+};
+
+/** "aes192-cbc" OID-identified algorithm */
+struct asn1_algorithm aes_192_cbc_algorithm __asn1_algorithm = {
+ .name = "aes192-cbc",
+ .cipher = &aes_cbc_algorithm,
+ .oid = ASN1_CURSOR ( oid_aes_192_cbc ),
+ .parse = asn1_parse_cbc,
+};
+
+/** "aes256-cbc" OID-identified algorithm */
+struct asn1_algorithm aes_256_cbc_algorithm __asn1_algorithm = {
+ .name = "aes256-cbc",
+ .cipher = &aes_cbc_algorithm,
+ .oid = ASN1_CURSOR ( oid_aes_256_cbc ),
+ .parse = asn1_parse_cbc,
+};
diff --git a/src/crypto/mishmash/oid_aes_gcm.c b/src/crypto/mishmash/oid_aes_gcm.c
new file mode 100644
index 0000000..af1432d
--- /dev/null
+++ b/src/crypto/mishmash/oid_aes_gcm.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/aes.h>
+#include <ipxe/asn1.h>
+
+/** "aes128-gcm" object identifier */
+static uint8_t oid_aes_128_gcm[] = { ASN1_OID_AES128_GCM };
+
+/** "aes192-gcm" object identifier */
+static uint8_t oid_aes_192_gcm[] = { ASN1_OID_AES192_GCM };
+
+/** "aes256-gcm" object identifier */
+static uint8_t oid_aes_256_gcm[] = { ASN1_OID_AES256_GCM };
+
+/** "aes128-gcm" OID-identified algorithm */
+struct asn1_algorithm aes_128_gcm_algorithm __asn1_algorithm = {
+ .name = "aes128-gcm",
+ .cipher = &aes_gcm_algorithm,
+ .oid = ASN1_CURSOR ( oid_aes_128_gcm ),
+ .parse = asn1_parse_gcm,
+};
+
+/** "aes192-gcm" OID-identified algorithm */
+struct asn1_algorithm aes_192_gcm_algorithm __asn1_algorithm = {
+ .name = "aes192-gcm",
+ .cipher = &aes_gcm_algorithm,
+ .oid = ASN1_CURSOR ( oid_aes_192_gcm ),
+ .parse = asn1_parse_gcm,
+};
+
+/** "aes256-gcm" OID-identified algorithm */
+struct asn1_algorithm aes_256_gcm_algorithm __asn1_algorithm = {
+ .name = "aes256-gcm",
+ .cipher = &aes_gcm_algorithm,
+ .oid = ASN1_CURSOR ( oid_aes_256_gcm ),
+ .parse = asn1_parse_gcm,
+};
diff --git a/src/crypto/ocsp.c b/src/crypto/ocsp.c
index cc957b4..e65f718 100644
--- a/src/crypto/ocsp.c
+++ b/src/crypto/ocsp.c
@@ -844,10 +844,9 @@ static int ocsp_check_signature ( struct ocsp_check *ocsp,
struct ocsp_response *response = &ocsp->response;
struct digest_algorithm *digest = response->algorithm->digest;
struct pubkey_algorithm *pubkey = response->algorithm->pubkey;
- struct x509_public_key *public_key = &signer->subject.public_key;
+ struct asn1_cursor *key = &signer->subject.public_key.raw;
uint8_t digest_ctx[ digest->ctxsize ];
uint8_t digest_out[ digest->digestsize ];
- uint8_t pubkey_ctx[ pubkey->ctxsize ];
int rc;
/* Generate digest */
@@ -856,30 +855,18 @@ static int ocsp_check_signature ( struct ocsp_check *ocsp,
response->tbs.len );
digest_final ( digest, digest_ctx, digest_out );
- /* Initialise public-key algorithm */
- if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
- public_key->raw.len ) ) != 0 ) {
- DBGC ( ocsp, "OCSP %p \"%s\" could not initialise public key: "
- "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
- goto err_init;
- }
-
/* Verify digest */
- if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
+ if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
response->signature.data,
response->signature.len ) ) != 0 ) {
DBGC ( ocsp, "OCSP %p \"%s\" signature verification failed: "
"%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
- goto err_verify;
+ return rc;
}
DBGC2 ( ocsp, "OCSP %p \"%s\" signature is correct\n",
ocsp, x509_name ( ocsp->cert ) );
-
- err_verify:
- pubkey_final ( pubkey, pubkey_ctx );
- err_init:
- return rc;
+ return 0;
}
/**
diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c
index 16c67d8..19472c1 100644
--- a/src/crypto/rsa.c
+++ b/src/crypto/rsa.c
@@ -47,6 +47,28 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define EINFO_EACCES_VERIFY \
__einfo_uniqify ( EINFO_EACCES, 0x01, "RSA signature incorrect" )
+/** An RSA context */
+struct rsa_context {
+ /** Allocated memory */
+ void *dynamic;
+ /** Modulus */
+ bigint_element_t *modulus0;
+ /** Modulus size */
+ unsigned int size;
+ /** Modulus length */
+ size_t max_len;
+ /** Exponent */
+ bigint_element_t *exponent0;
+ /** Exponent size */
+ unsigned int exponent_size;
+ /** Input buffer */
+ bigint_element_t *input0;
+ /** Output buffer */
+ bigint_element_t *output0;
+ /** Temporary working space for modular exponentiation */
+ void *tmp;
+};
+
/**
* Identify RSA prefix
*
@@ -69,10 +91,9 @@ rsa_find_prefix ( struct digest_algorithm *digest ) {
*
* @v context RSA context
*/
-static void rsa_free ( struct rsa_context *context ) {
+static inline void rsa_free ( struct rsa_context *context ) {
free ( context->dynamic );
- context->dynamic = NULL;
}
/**
@@ -98,9 +119,6 @@ static int rsa_alloc ( struct rsa_context *context, size_t modulus_len,
uint8_t tmp[tmp_len];
} __attribute__ (( packed )) *dynamic;
- /* Free any existing dynamic storage */
- rsa_free ( context );
-
/* Allocate dynamic storage */
dynamic = malloc ( sizeof ( *dynamic ) );
if ( ! dynamic )
@@ -231,29 +249,23 @@ static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
/**
* Initialise RSA cipher
*
- * @v ctx RSA context
+ * @v context RSA context
* @v key Key
- * @v key_len Length of key
* @ret rc Return status code
*/
-static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
- struct rsa_context *context = ctx;
+static int rsa_init ( struct rsa_context *context,
+ const struct asn1_cursor *key ) {
struct asn1_cursor modulus;
struct asn1_cursor exponent;
- struct asn1_cursor cursor;
int rc;
/* Initialise context */
memset ( context, 0, sizeof ( *context ) );
- /* Initialise cursor */
- cursor.data = key;
- cursor.len = key_len;
-
/* Parse modulus and exponent */
- if ( ( rc = rsa_parse_mod_exp ( &modulus, &exponent, &cursor ) ) != 0 ){
+ if ( ( rc = rsa_parse_mod_exp ( &modulus, &exponent, key ) ) != 0 ){
DBGC ( context, "RSA %p invalid modulus/exponent:\n", context );
- DBGC_HDA ( context, 0, cursor.data, cursor.len );
+ DBGC_HDA ( context, 0, key->data, key->len );
goto err_parse;
}
@@ -283,13 +295,22 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
/**
* Calculate RSA maximum output length
*
- * @v ctx RSA context
+ * @v key Key
* @ret max_len Maximum output length
*/
-static size_t rsa_max_len ( void *ctx ) {
- struct rsa_context *context = ctx;
+static size_t rsa_max_len ( const struct asn1_cursor *key ) {
+ struct asn1_cursor modulus;
+ struct asn1_cursor exponent;
+ int rc;
+
+ /* Parse moduli and exponents */
+ if ( ( rc = rsa_parse_mod_exp ( &modulus, &exponent, key ) ) != 0 ) {
+ /* Return a zero maximum length on error */
+ return 0;
+ }
- return context->max_len;
+ /* Output length can never exceed modulus length */
+ return modulus.len;
}
/**
@@ -320,111 +341,147 @@ static void rsa_cipher ( struct rsa_context *context,
/**
* Encrypt using RSA
*
- * @v ctx RSA context
+ * @v key Key
* @v plaintext Plaintext
* @v plaintext_len Length of plaintext
* @v ciphertext Ciphertext
* @ret ciphertext_len Length of ciphertext, or negative error
*/
-static int rsa_encrypt ( void *ctx, const void *plaintext,
+static int rsa_encrypt ( const struct asn1_cursor *key, const void *plaintext,
size_t plaintext_len, void *ciphertext ) {
- struct rsa_context *context = ctx;
+ struct rsa_context context;
void *temp;
uint8_t *encoded;
- size_t max_len = ( context->max_len - 11 );
- size_t random_nz_len = ( max_len - plaintext_len + 8 );
+ size_t max_len;
+ size_t random_nz_len;
int rc;
+ DBGC ( &context, "RSA %p encrypting:\n", &context );
+ DBGC_HDA ( &context, 0, plaintext, plaintext_len );
+
+ /* Initialise context */
+ if ( ( rc = rsa_init ( &context, key ) ) != 0 )
+ goto err_init;
+
+ /* Calculate lengths */
+ max_len = ( context.max_len - 11 );
+ random_nz_len = ( max_len - plaintext_len + 8 );
+
/* Sanity check */
if ( plaintext_len > max_len ) {
- DBGC ( context, "RSA %p plaintext too long (%zd bytes, max "
- "%zd)\n", context, plaintext_len, max_len );
- return -ERANGE;
+ DBGC ( &context, "RSA %p plaintext too long (%zd bytes, max "
+ "%zd)\n", &context, plaintext_len, max_len );
+ rc = -ERANGE;
+ goto err_sanity;
}
- DBGC ( context, "RSA %p encrypting:\n", context );
- DBGC_HDA ( context, 0, plaintext, plaintext_len );
/* Construct encoded message (using the big integer output
* buffer as temporary storage)
*/
- temp = context->output0;
+ temp = context.output0;
encoded = temp;
encoded[0] = 0x00;
encoded[1] = 0x02;
if ( ( rc = get_random_nz ( &encoded[2], random_nz_len ) ) != 0 ) {
- DBGC ( context, "RSA %p could not generate random data: %s\n",
- context, strerror ( rc ) );
- return rc;
+ DBGC ( &context, "RSA %p could not generate random data: %s\n",
+ &context, strerror ( rc ) );
+ goto err_random;
}
encoded[ 2 + random_nz_len ] = 0x00;
- memcpy ( &encoded[ context->max_len - plaintext_len ],
+ memcpy ( &encoded[ context.max_len - plaintext_len ],
plaintext, plaintext_len );
/* Encipher the encoded message */
- rsa_cipher ( context, encoded, ciphertext );
- DBGC ( context, "RSA %p encrypted:\n", context );
- DBGC_HDA ( context, 0, ciphertext, context->max_len );
+ rsa_cipher ( &context, encoded, ciphertext );
+ DBGC ( &context, "RSA %p encrypted:\n", &context );
+ DBGC_HDA ( &context, 0, ciphertext, context.max_len );
- return context->max_len;
+ /* Free context */
+ rsa_free ( &context );
+
+ return context.max_len;
+
+ err_random:
+ err_sanity:
+ rsa_free ( &context );
+ err_init:
+ return rc;
}
/**
* Decrypt using RSA
*
- * @v ctx RSA context
+ * @v key Key
* @v ciphertext Ciphertext
* @v ciphertext_len Ciphertext length
* @v plaintext Plaintext
* @ret plaintext_len Plaintext length, or negative error
*/
-static int rsa_decrypt ( void *ctx, const void *ciphertext,
+static int rsa_decrypt ( const struct asn1_cursor *key, const void *ciphertext,
size_t ciphertext_len, void *plaintext ) {
- struct rsa_context *context = ctx;
+ struct rsa_context context;
void *temp;
uint8_t *encoded;
uint8_t *end;
uint8_t *zero;
uint8_t *start;
size_t plaintext_len;
+ int rc;
+
+ DBGC ( &context, "RSA %p decrypting:\n", &context );
+ DBGC_HDA ( &context, 0, ciphertext, ciphertext_len );
+
+ /* Initialise context */
+ if ( ( rc = rsa_init ( &context, key ) ) != 0 )
+ goto err_init;
/* Sanity check */
- if ( ciphertext_len != context->max_len ) {
- DBGC ( context, "RSA %p ciphertext incorrect length (%zd "
+ if ( ciphertext_len != context.max_len ) {
+ DBGC ( &context, "RSA %p ciphertext incorrect length (%zd "
"bytes, should be %zd)\n",
- context, ciphertext_len, context->max_len );
- return -ERANGE;
+ &context, ciphertext_len, context.max_len );
+ rc = -ERANGE;
+ goto err_sanity;
}
- DBGC ( context, "RSA %p decrypting:\n", context );
- DBGC_HDA ( context, 0, ciphertext, ciphertext_len );
/* Decipher the message (using the big integer input buffer as
* temporary storage)
*/
- temp = context->input0;
+ temp = context.input0;
encoded = temp;
- rsa_cipher ( context, ciphertext, encoded );
+ rsa_cipher ( &context, ciphertext, encoded );
/* Parse the message */
- end = ( encoded + context->max_len );
- if ( ( encoded[0] != 0x00 ) || ( encoded[1] != 0x02 ) )
- goto invalid;
+ end = ( encoded + context.max_len );
+ if ( ( encoded[0] != 0x00 ) || ( encoded[1] != 0x02 ) ) {
+ rc = -EINVAL;
+ goto err_invalid;
+ }
zero = memchr ( &encoded[2], 0, ( end - &encoded[2] ) );
- if ( ! zero )
- goto invalid;
+ if ( ! zero ) {
+ rc = -EINVAL;
+ goto err_invalid;
+ }
start = ( zero + 1 );
plaintext_len = ( end - start );
/* Copy out message */
memcpy ( plaintext, start, plaintext_len );
- DBGC ( context, "RSA %p decrypted:\n", context );
- DBGC_HDA ( context, 0, plaintext, plaintext_len );
+ DBGC ( &context, "RSA %p decrypted:\n", &context );
+ DBGC_HDA ( &context, 0, plaintext, plaintext_len );
+
+ /* Free context */
+ rsa_free ( &context );
return plaintext_len;
- invalid:
- DBGC ( context, "RSA %p invalid decrypted message:\n", context );
- DBGC_HDA ( context, 0, encoded, context->max_len );
- return -EINVAL;
+ err_invalid:
+ DBGC ( &context, "RSA %p invalid decrypted message:\n", &context );
+ DBGC_HDA ( &context, 0, encoded, context.max_len );
+ err_sanity:
+ rsa_free ( &context );
+ err_init:
+ return rc;
}
/**
@@ -458,9 +515,9 @@ static int rsa_encode_digest ( struct rsa_context *context,
/* Sanity check */
max_len = ( context->max_len - 11 );
if ( digestinfo_len > max_len ) {
- DBGC ( context, "RSA %p %s digestInfo too long (%zd bytes, max"
- "%zd)\n",
- context, digest->name, digestinfo_len, max_len );
+ DBGC ( context, "RSA %p %s digestInfo too long (%zd bytes, "
+ "max %zd)\n", context, digest->name, digestinfo_len,
+ max_len );
return -ERANGE;
}
DBGC ( context, "RSA %p encoding %s digest:\n",
@@ -488,137 +545,148 @@ static int rsa_encode_digest ( struct rsa_context *context,
/**
* Sign digest value using RSA
*
- * @v ctx RSA context
+ * @v key Key
* @v digest Digest algorithm
* @v value Digest value
* @v signature Signature
* @ret signature_len Signature length, or negative error
*/
-static int rsa_sign ( void *ctx, struct digest_algorithm *digest,
- const void *value, void *signature ) {
- struct rsa_context *context = ctx;
+static int rsa_sign ( const struct asn1_cursor *key,
+ struct digest_algorithm *digest, const void *value,
+ void *signature ) {
+ struct rsa_context context;
void *temp;
int rc;
- DBGC ( context, "RSA %p signing %s digest:\n", context, digest->name );
- DBGC_HDA ( context, 0, value, digest->digestsize );
+ DBGC ( &context, "RSA %p signing %s digest:\n",
+ &context, digest->name );
+ DBGC_HDA ( &context, 0, value, digest->digestsize );
+
+ /* Initialise context */
+ if ( ( rc = rsa_init ( &context, key ) ) != 0 )
+ goto err_init;
/* Encode digest (using the big integer output buffer as
* temporary storage)
*/
- temp = context->output0;
- if ( ( rc = rsa_encode_digest ( context, digest, value, temp ) ) != 0 )
- return rc;
+ temp = context.output0;
+ if ( ( rc = rsa_encode_digest ( &context, digest, value, temp ) ) != 0 )
+ goto err_encode;
/* Encipher the encoded digest */
- rsa_cipher ( context, temp, signature );
- DBGC ( context, "RSA %p signed %s digest:\n", context, digest->name );
- DBGC_HDA ( context, 0, signature, context->max_len );
+ rsa_cipher ( &context, temp, signature );
+ DBGC ( &context, "RSA %p signed %s digest:\n", &context, digest->name );
+ DBGC_HDA ( &context, 0, signature, context.max_len );
+
+ /* Free context */
+ rsa_free ( &context );
- return context->max_len;
+ return context.max_len;
+
+ err_encode:
+ rsa_free ( &context );
+ err_init:
+ return rc;
}
/**
* Verify signed digest value using RSA
*
- * @v ctx RSA context
+ * @v key Key
* @v digest Digest algorithm
* @v value Digest value
* @v signature Signature
* @v signature_len Signature length
* @ret rc Return status code
*/
-static int rsa_verify ( void *ctx, struct digest_algorithm *digest,
- const void *value, const void *signature,
- size_t signature_len ) {
- struct rsa_context *context = ctx;
+static int rsa_verify ( const struct asn1_cursor *key,
+ struct digest_algorithm *digest, const void *value,
+ const void *signature, size_t signature_len ) {
+ struct rsa_context context;
void *temp;
void *expected;
void *actual;
int rc;
+ DBGC ( &context, "RSA %p verifying %s digest:\n",
+ &context, digest->name );
+ DBGC_HDA ( &context, 0, value, digest->digestsize );
+ DBGC_HDA ( &context, 0, signature, signature_len );
+
+ /* Initialise context */
+ if ( ( rc = rsa_init ( &context, key ) ) != 0 )
+ goto err_init;
+
/* Sanity check */
- if ( signature_len != context->max_len ) {
- DBGC ( context, "RSA %p signature incorrect length (%zd "
+ if ( signature_len != context.max_len ) {
+ DBGC ( &context, "RSA %p signature incorrect length (%zd "
"bytes, should be %zd)\n",
- context, signature_len, context->max_len );
- return -ERANGE;
+ &context, signature_len, context.max_len );
+ rc = -ERANGE;
+ goto err_sanity;
}
- DBGC ( context, "RSA %p verifying %s digest:\n",
- context, digest->name );
- DBGC_HDA ( context, 0, value, digest->digestsize );
- DBGC_HDA ( context, 0, signature, signature_len );
/* Decipher the signature (using the big integer input buffer
* as temporary storage)
*/
- temp = context->input0;
+ temp = context.input0;
expected = temp;
- rsa_cipher ( context, signature, expected );
- DBGC ( context, "RSA %p deciphered signature:\n", context );
- DBGC_HDA ( context, 0, expected, context->max_len );
+ rsa_cipher ( &context, signature, expected );
+ DBGC ( &context, "RSA %p deciphered signature:\n", &context );
+ DBGC_HDA ( &context, 0, expected, context.max_len );
/* Encode digest (using the big integer output buffer as
* temporary storage)
*/
- temp = context->output0;
+ temp = context.output0;
actual = temp;
- if ( ( rc = rsa_encode_digest ( context, digest, value, actual ) ) !=0 )
- return rc;
+ if ( ( rc = rsa_encode_digest ( &context, digest, value,
+ actual ) ) != 0 )
+ goto err_encode;
/* Verify the signature */
- if ( memcmp ( actual, expected, context->max_len ) != 0 ) {
- DBGC ( context, "RSA %p signature verification failed\n",
- context );
- return -EACCES_VERIFY;
+ if ( memcmp ( actual, expected, context.max_len ) != 0 ) {
+ DBGC ( &context, "RSA %p signature verification failed\n",
+ &context );
+ rc = -EACCES_VERIFY;
+ goto err_verify;
}
- DBGC ( context, "RSA %p signature verified successfully\n", context );
- return 0;
-}
+ /* Free context */
+ rsa_free ( &context );
-/**
- * Finalise RSA cipher
- *
- * @v ctx RSA context
- */
-static void rsa_final ( void *ctx ) {
- struct rsa_context *context = ctx;
+ DBGC ( &context, "RSA %p signature verified successfully\n", &context );
+ return 0;
- rsa_free ( context );
+ err_verify:
+ err_encode:
+ err_sanity:
+ rsa_free ( &context );
+ err_init:
+ return rc;
}
/**
* Check for matching RSA public/private key pair
*
* @v private_key Private key
- * @v private_key_len Private key length
* @v public_key Public key
- * @v public_key_len Public key length
* @ret rc Return status code
*/
-static int rsa_match ( const void *private_key, size_t private_key_len,
- const void *public_key, size_t public_key_len ) {
+static int rsa_match ( const struct asn1_cursor *private_key,
+ const struct asn1_cursor *public_key ) {
struct asn1_cursor private_modulus;
struct asn1_cursor private_exponent;
- struct asn1_cursor private_cursor;
struct asn1_cursor public_modulus;
struct asn1_cursor public_exponent;
- struct asn1_cursor public_cursor;
int rc;
- /* Initialise cursors */
- private_cursor.data = private_key;
- private_cursor.len = private_key_len;
- public_cursor.data = public_key;
- public_cursor.len = public_key_len;
-
/* Parse moduli and exponents */
if ( ( rc = rsa_parse_mod_exp ( &private_modulus, &private_exponent,
- &private_cursor ) ) != 0 )
+ private_key ) ) != 0 )
return rc;
if ( ( rc = rsa_parse_mod_exp ( &public_modulus, &public_exponent,
- &public_cursor ) ) != 0 )
+ public_key ) ) != 0 )
return rc;
/* Compare moduli */
@@ -631,14 +699,11 @@ static int rsa_match ( const void *private_key, size_t private_key_len,
/** RSA public-key algorithm */
struct pubkey_algorithm rsa_algorithm = {
.name = "rsa",
- .ctxsize = RSA_CTX_SIZE,
- .init = rsa_init,
.max_len = rsa_max_len,
.encrypt = rsa_encrypt,
.decrypt = rsa_decrypt,
.sign = rsa_sign,
.verify = rsa_verify,
- .final = rsa_final,
.match = rsa_match,
};
diff --git a/src/crypto/x509.c b/src/crypto/x509.c
index 9231809..4101c80 100644
--- a/src/crypto/x509.c
+++ b/src/crypto/x509.c
@@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/rsa.h>
#include <ipxe/rootcert.h>
#include <ipxe/certstore.h>
+#include <ipxe/privkey.h>
#include <ipxe/socket.h>
#include <ipxe/in.h>
#include <ipxe/image.h>
@@ -1078,7 +1079,7 @@ int x509_certificate ( const void *data, size_t len,
asn1_shrink_any ( &cursor );
/* Return stored certificate, if present */
- if ( ( *cert = certstore_find ( &cursor ) ) != NULL ) {
+ if ( ( *cert = x509_find ( NULL, &cursor ) ) != NULL ) {
/* Add caller's reference */
x509_get ( *cert );
@@ -1124,7 +1125,6 @@ static int x509_check_signature ( struct x509_certificate *cert,
struct pubkey_algorithm *pubkey = algorithm->pubkey;
uint8_t digest_ctx[ digest->ctxsize ];
uint8_t digest_out[ digest->digestsize ];
- uint8_t pubkey_ctx[ pubkey->ctxsize ];
int rc;
/* Sanity check */
@@ -1148,14 +1148,8 @@ static int x509_check_signature ( struct x509_certificate *cert,
}
/* Verify signature using signer's public key */
- if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
- public_key->raw.len ) ) != 0 ) {
- DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: "
- "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
- goto err_pubkey_init;
- }
- if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
- signature->value.data,
+ if ( ( rc = pubkey_verify ( pubkey, &public_key->raw, digest,
+ digest_out, signature->value.data,
signature->value.len ) ) != 0 ) {
DBGC ( cert, "X509 %p \"%s\" signature verification failed: "
"%s\n", cert, x509_name ( cert ), strerror ( rc ) );
@@ -1166,8 +1160,6 @@ static int x509_check_signature ( struct x509_certificate *cert,
rc = 0;
err_pubkey_verify:
- pubkey_final ( pubkey, pubkey_ctx );
- err_pubkey_init:
err_mismatch:
return rc;
}
@@ -1711,25 +1703,139 @@ void x509_truncate ( struct x509_chain *chain, struct x509_link *link ) {
}
/**
+ * Mark X.509 certificate as found
+ *
+ * @v store Certificate store
+ * @v cert X.509 certificate
+ * @ret cert X.509 certificate
+ */
+static struct x509_certificate * x509_found ( struct x509_chain *store,
+ struct x509_certificate *cert ) {
+
+ /* Sanity check */
+ assert ( store != NULL );
+
+ /* Mark as found, if applicable */
+ if ( store->found )
+ store->found ( store, cert );
+
+ return cert;
+}
+
+/**
+ * Identify X.509 certificate by raw certificate data
+ *
+ * @v store Certificate store, or NULL to use default
+ * @v raw Raw certificate data
+ * @ret cert X.509 certificate, or NULL if not found
+ */
+struct x509_certificate * x509_find ( struct x509_chain *store,
+ const struct asn1_cursor *raw ) {
+ struct x509_link *link;
+ struct x509_certificate *cert;
+
+ /* Use default certificate store if none specified */
+ if ( ! store )
+ store = &certstore;
+
+ /* Search for certificate within store */
+ list_for_each_entry ( link, &store->links, list ) {
+
+ /* Check raw certificate data */
+ cert = link->cert;
+ if ( asn1_compare ( raw, &cert->raw ) == 0 )
+ return x509_found ( store, cert );
+ }
+
+ return NULL;
+}
+
+/**
* Identify X.509 certificate by subject
*
- * @v certs X.509 certificate list
+ * @v store Certificate store, or NULL to use default
* @v subject Subject
* @ret cert X.509 certificate, or NULL if not found
*/
-static struct x509_certificate *
-x509_find_subject ( struct x509_chain *certs,
+struct x509_certificate *
+x509_find_subject ( struct x509_chain *store,
const struct asn1_cursor *subject ) {
struct x509_link *link;
struct x509_certificate *cert;
+ /* Use default certificate store if none specified */
+ if ( ! store )
+ store = &certstore;
+
/* Scan through certificate list */
- list_for_each_entry ( link, &certs->links, list ) {
+ list_for_each_entry ( link, &store->links, list ) {
/* Check subject */
cert = link->cert;
if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
- return cert;
+ return x509_found ( store, cert );
+ }
+
+ return NULL;
+}
+
+/**
+ * Identify X.509 certificate by issuer and serial number
+ *
+ * @v store Certificate store, or NULL to use default
+ * @v issuer Issuer
+ * @v serial Serial number
+ * @ret cert X.509 certificate, or NULL if not found
+ */
+struct x509_certificate *
+x509_find_issuer_serial ( struct x509_chain *store,
+ const struct asn1_cursor *issuer,
+ const struct asn1_cursor *serial ) {
+ struct x509_link *link;
+ struct x509_certificate *cert;
+
+ /* Use default certificate store if none specified */
+ if ( ! store )
+ store = &certstore;
+
+ /* Scan through certificate list */
+ list_for_each_entry ( link, &store->links, list ) {
+
+ /* Check issuer and serial number */
+ cert = link->cert;
+ if ( ( asn1_compare ( issuer, &cert->issuer.raw ) == 0 ) &&
+ ( asn1_compare ( serial, &cert->serial.raw ) == 0 ) )
+ return x509_found ( store, cert );
+ }
+
+ return NULL;
+}
+
+/**
+ * Identify X.509 certificate by corresponding public key
+ *
+ * @v store Certificate store, or NULL to use default
+ * @v key Private key
+ * @ret cert X.509 certificate, or NULL if not found
+ */
+struct x509_certificate * x509_find_key ( struct x509_chain *store,
+ struct private_key *key ) {
+ struct x509_link *link;
+ struct x509_certificate *cert;
+
+ /* Use default certificate store if none specified */
+ if ( ! store )
+ store = &certstore;
+
+ /* Scan through certificate list */
+ list_for_each_entry ( link, &store->links, list ) {
+
+ /* Check public key */
+ cert = link->cert;
+ if ( pubkey_match ( cert->signature_algorithm->pubkey,
+ privkey_cursor ( key ),
+ &cert->subject.public_key.raw ) == 0 )
+ return x509_found ( store, cert );
}
return NULL;
@@ -1739,13 +1845,13 @@ x509_find_subject ( struct x509_chain *certs,
* Append X.509 certificates to X.509 certificate chain
*
* @v chain X.509 certificate chain
- * @v certs X.509 certificate list
+ * @v store Certificate store, or NULL to use default
* @ret rc Return status code
*
* Certificates will be automatically appended to the chain based upon
* the subject and issuer names.
*/
-int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) {
+int x509_auto_append ( struct x509_chain *chain, struct x509_chain *store ) {
struct x509_certificate *cert;
struct x509_certificate *previous;
int rc;
@@ -1762,7 +1868,7 @@ int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) {
/* Find issuing certificate */
previous = cert;
- cert = x509_find_subject ( certs, &cert->issuer.raw );
+ cert = x509_find_subject ( store, &cert->issuer.raw );
if ( ! cert )
break;
if ( cert == previous )
@@ -1791,10 +1897,6 @@ int x509_validate_chain ( struct x509_chain *chain, time_t time,
struct x509_link *link;
int rc;
- /* Use default certificate store if none specified */
- if ( ! store )
- store = &certstore;
-
/* Append any applicable certificates from the certificate store */
if ( ( rc = x509_auto_append ( chain, store ) ) != 0 )
return rc;
diff --git a/src/drivers/bus/ecam.c b/src/drivers/bus/ecam.c
index 5e3debd..cde5952 100644
--- a/src/drivers/bus/ecam.c
+++ b/src/drivers/bus/ecam.c
@@ -276,6 +276,7 @@ int ecam_write ( struct pci_device *pci, unsigned int location,
return 0;
}
+PROVIDE_PCIAPI_INLINE ( ecam, pci_can_probe );
PROVIDE_PCIAPI ( ecam, pci_discover, ecam_discover );
PROVIDE_PCIAPI_INLINE ( ecam, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( ecam, pci_read_config_word );
diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c
index 92b3896..05c9a5c 100644
--- a/src/drivers/bus/pci.c
+++ b/src/drivers/bus/pci.c
@@ -361,6 +361,10 @@ static int pcibus_probe ( struct root_device *rootdev ) {
uint32_t busdevfn = 0;
int rc;
+ /* Skip automatic probing if prohibited */
+ if ( ! pci_can_probe() )
+ return 0;
+
do {
/* Allocate struct pci_device */
if ( ! pci )
diff --git a/src/drivers/net/ena.c b/src/drivers/net/ena.c
index 7ce5b9e..89483ea 100644
--- a/src/drivers/net/ena.c
+++ b/src/drivers/net/ena.c
@@ -560,8 +560,11 @@ static int ena_create_cq ( struct ena_nic *ena, struct ena_cq *cq ) {
req->create_cq.address = cpu_to_le64 ( virt_to_bus ( cq->cqe.raw ) );
/* Issue request */
- if ( ( rc = ena_admin ( ena, req, &rsp ) ) != 0 )
+ if ( ( rc = ena_admin ( ena, req, &rsp ) ) != 0 ) {
+ DBGC ( ena, "ENA %p CQ%d creation failed (broken firmware?)\n",
+ ena, cq->id );
goto err_admin;
+ }
/* Parse response */
cq->id = le16_to_cpu ( rsp->create_cq.id );
@@ -1163,7 +1166,7 @@ static int ena_probe ( struct pci_device *pci ) {
}
ena->info = info;
memset ( info, 0, PAGE_SIZE );
- info->type = cpu_to_le32 ( ENA_HOST_INFO_TYPE_LINUX );
+ info->type = cpu_to_le32 ( ENA_HOST_INFO_TYPE_IPXE );
snprintf ( info->dist_str, sizeof ( info->dist_str ), "%s",
( product_name[0] ? product_name : product_short_name ) );
snprintf ( info->kernel_str, sizeof ( info->kernel_str ), "%s",
diff --git a/src/drivers/net/ena.h b/src/drivers/net/ena.h
index 0f280c7..9fda997 100644
--- a/src/drivers/net/ena.h
+++ b/src/drivers/net/ena.h
@@ -191,14 +191,17 @@ struct ena_host_info {
uint32_t features;
} __attribute__ (( packed ));
-/** Linux operating system type
+/** Operating system type
*
- * There is a defined "iPXE" operating system type (with value 5).
- * However, some very broken versions of the ENA firmware will refuse
- * to allow a completion queue to be created if the "iPXE" type is
- * used.
+ * Some very broken older versions of the ENA firmware will refuse to
+ * allow a completion queue to be created if "iPXE" (type 5) is used,
+ * and require us to pretend that we are "Linux" (type 1) instead.
+ *
+ * The ENA team at AWS assures us that the entire AWS fleet has been
+ * upgraded to fix this bug, and that we are now safe to use the
+ * correct operating system type value.
*/
-#define ENA_HOST_INFO_TYPE_LINUX 1
+#define ENA_HOST_INFO_TYPE_IPXE 5
/** Driver version
*
diff --git a/src/drivers/net/etherfabric.c b/src/drivers/net/etherfabric.c
index b40596b..be30b71 100644
--- a/src/drivers/net/etherfabric.c
+++ b/src/drivers/net/etherfabric.c
@@ -2225,13 +2225,16 @@ falcon_xaui_link_ok ( struct efab_nic *efab )
sync = ( sync == FCN_XX_SYNC_STAT_DECODE_SYNCED );
link_ok = align_done && sync;
- }
- /* Clear link status ready for next read */
- EFAB_SET_DWORD_FIELD ( reg, FCN_XX_COMMA_DET, FCN_XX_COMMA_DET_RESET );
- EFAB_SET_DWORD_FIELD ( reg, FCN_XX_CHARERR, FCN_XX_CHARERR_RESET);
- EFAB_SET_DWORD_FIELD ( reg, FCN_XX_DISPERR, FCN_XX_DISPERR_RESET);
- falcon_xmac_writel ( efab, &reg, FCN_XX_CORE_STAT_REG_MAC );
+ /* Clear link status ready for next read */
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_COMMA_DET,
+ FCN_XX_COMMA_DET_RESET );
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_CHARERR,
+ FCN_XX_CHARERR_RESET );
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_DISPERR,
+ FCN_XX_DISPERR_RESET );
+ falcon_xmac_writel ( efab, &reg, FCN_XX_CORE_STAT_REG_MAC );
+ }
has_phyxs = ( efab->phy_op->mmds & ( 1 << MDIO_MMD_PHYXS ) );
if ( link_ok && has_phyxs ) {
diff --git a/src/drivers/net/gve.c b/src/drivers/net/gve.c
index 7f86dd2..0193e76 100644
--- a/src/drivers/net/gve.c
+++ b/src/drivers/net/gve.c
@@ -117,10 +117,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
EUNIQ ( EINFO_EIO, ( (status) & 0x1f ), \
EIO_ADMIN_UNSET, EIO_ADMIN_ABORTED, EIO_ADMIN_EXISTS, \
EIO_ADMIN_CANCELLED, EIO_ADMIN_DATALOSS, \
- EIO_ADMIN_DEADLINE, EIO_ADMIN_NOT_FOUND, \
- EIO_ADMIN_RANGE, EIO_ADMIN_PERM, EIO_ADMIN_UNAUTH, \
- EIO_ADMIN_RESOURCE, EIO_ADMIN_UNAVAIL, \
- EIO_ADMIN_NOTSUP, EIO_ADMIN_UNKNOWN )
+ EIO_ADMIN_DEADLINE, EIO_ADMIN_PRECONDITION, \
+ EIO_ADMIN_INTERNAL, EIO_ADMIN_INVAL, \
+ EIO_ADMIN_NOT_FOUND, EIO_ADMIN_RANGE, EIO_ADMIN_PERM, \
+ EIO_ADMIN_UNAUTH, EIO_ADMIN_RESOURCE, \
+ EIO_ADMIN_UNAVAIL, EIO_ADMIN_NOTSUP, EIO_ADMIN_UNKNOWN )
/******************************************************************************
*
diff --git a/src/drivers/net/iphone.c b/src/drivers/net/iphone.c
index bbac527..08459a6 100644
--- a/src/drivers/net/iphone.c
+++ b/src/drivers/net/iphone.c
@@ -362,18 +362,9 @@ static int icert_cert ( struct icert *icert, struct asn1_cursor *subject,
struct asn1_builder raw = { NULL, 0 };
uint8_t digest_ctx[SHA256_CTX_SIZE];
uint8_t digest_out[SHA256_DIGEST_SIZE];
- uint8_t pubkey_ctx[RSA_CTX_SIZE];
int len;
int rc;
- /* Initialise "private" key */
- if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, private->data,
- private->len ) ) != 0 ) {
- DBGC ( icert, "ICERT %p could not initialise private key: "
- "%s\n", icert, strerror ( rc ) );
- goto err_pubkey_init;
- }
-
/* Construct subjectPublicKeyInfo */
if ( ( rc = ( asn1_prepend_raw ( &spki, public->data, public->len ),
asn1_prepend_raw ( &spki, icert_nul,
@@ -407,14 +398,14 @@ static int icert_cert ( struct icert *icert, struct asn1_cursor *subject,
digest_update ( digest, digest_ctx, tbs.data, tbs.len );
digest_final ( digest, digest_ctx, digest_out );
- /* Construct signature */
- if ( ( rc = asn1_grow ( &raw, pubkey_max_len ( pubkey,
- pubkey_ctx ) ) ) != 0 ) {
+ /* Construct signature using "private" key */
+ if ( ( rc = asn1_grow ( &raw,
+ pubkey_max_len ( pubkey, private ) ) ) != 0 ) {
DBGC ( icert, "ICERT %p could not build signature: %s\n",
icert, strerror ( rc ) );
goto err_grow;
}
- if ( ( len = pubkey_sign ( pubkey, pubkey_ctx, digest, digest_out,
+ if ( ( len = pubkey_sign ( pubkey, private, digest, digest_out,
raw.data ) ) < 0 ) {
rc = len;
DBGC ( icert, "ICERT %p could not sign: %s\n",
@@ -453,8 +444,6 @@ static int icert_cert ( struct icert *icert, struct asn1_cursor *subject,
err_tbs:
free ( spki.data );
err_spki:
- pubkey_final ( pubkey, pubkey_ctx );
- err_pubkey_init:
return rc;
}
diff --git a/src/drivers/net/marvell/aqc1xx.c b/src/drivers/net/marvell/aqc1xx.c
new file mode 100644
index 0000000..b108bf7
--- /dev/null
+++ b/src/drivers/net/marvell/aqc1xx.c
@@ -0,0 +1,629 @@
+/** @file
+ *
+ * Marvell AQtion family network card driver.
+ *
+ * Copyright(C) 2017-2024 Marvell
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO,THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/malloc.h>
+#include <ipxe/pci.h>
+#include <ipxe/profile.h>
+
+#include "aqc1xx.h"
+
+extern struct atl_hw_ops atl_hw;
+extern struct atl_hw_ops atl2_hw;
+
+/** @file
+*
+* Marvell AQC network card driver
+*
+*/
+
+static int atl_ring_alloc ( const struct atl_nic *nic, struct atl_ring *ring,
+ uint32_t desc_size, uint32_t reg_base ) {
+ physaddr_t phy_addr;
+
+ /* Allocate ring buffer.*/
+ ring->length = ATL_RING_SIZE * desc_size;
+ ring->ring = dma_alloc ( nic->dma, &ring->map, ring->length,
+ ring->length );
+
+ if ( !ring->ring )
+ return -ENOMEM;
+
+ /* Initialize the descriptor ring */
+ memset ( ring->ring, 0, ring->length );
+
+ /* Program ring address */
+ phy_addr = dma ( &ring->map, ring->ring );
+
+ /* Write ring address (hi & low parts).*/
+ ATL_WRITE_REG ( ( uint32_t )phy_addr, reg_base );
+ ATL_WRITE_REG ( ( uint32_t ) ( ( ( uint64_t )phy_addr ) >> 32 ), reg_base + 4 );
+
+ /* Write ring length.*/
+ ATL_WRITE_REG ( ATL_RING_SIZE, reg_base + 8 );
+
+ ring->sw_head = ring->sw_tail = 0;
+
+ DBGC ( nic, "AQUANTIA: %p ring is at [%08llx,%08llx), reg base %#x\n",
+ nic, ( ( unsigned long long )phy_addr ),
+ ( ( unsigned long long ) phy_addr + ring->length ), reg_base );
+
+ return 0;
+}
+
+static void atl_ring_free ( struct atl_ring *ring ) {
+ dma_free ( &ring->map, ring->ring, ring->length );
+ ring->ring = NULL;
+ ring->length = 0;
+}
+
+static void atl_ring_next_dx ( unsigned int *val ) {
+ ++( *val );
+ if ( *val == ATL_RING_SIZE )
+ *val = 0;
+}
+
+int atl_ring_full ( const struct atl_ring *ring ) {
+ unsigned int tail = ring->sw_tail;
+ atl_ring_next_dx ( &tail );
+ return tail == ring->sw_head;
+}
+
+void atl_rx_ring_fill ( struct atl_nic *nic ) {
+ struct atl_desc_rx *rx;
+ struct io_buffer *iobuf;
+ physaddr_t address;
+ unsigned int refilled = 0;
+
+ /* Refill ring */
+ while ( !atl_ring_full ( &nic->rx_ring ) ) {
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_rx_iob ( ATL_RX_MAX_LEN, nic->dma );
+ if ( !iobuf ) {
+ /* Wait for next refill */
+ break;
+ }
+
+ /* Get next receive descriptor */
+ rx = ( struct atl_desc_rx * )nic->rx_ring.ring +
+ nic->rx_ring.sw_tail;
+
+ /* Populate receive descriptor */
+ address = iob_dma ( iobuf );
+ rx->data_addr = address;
+ rx->hdr_addr = 0;
+
+ /* Record I/O buffer */
+ assert ( nic->iobufs[nic->rx_ring.sw_tail] == NULL );
+ nic->iobufs[nic->rx_ring.sw_tail] = iobuf;
+
+ DBGC( nic, "AQUANTIA: RX[%d] is [%llx,%llx)\n",
+ nic->rx_ring.sw_tail,
+ ( ( unsigned long long )address ),
+ ( ( unsigned long long )address + ATL_RX_MAX_LEN ) );
+
+ atl_ring_next_dx ( &nic->rx_ring.sw_tail );
+ refilled++;
+ }
+
+ /* Push descriptors to card, if applicable */
+ if ( refilled ) {
+ wmb();
+ ATL_WRITE_REG ( nic->rx_ring.sw_tail, ATL_RING_TAIL_PTR );
+ }
+}
+
+/**
+* Open network device
+*
+* @v netdev Network device
+* @ret rc Return status code
+*/
+static int atl_open ( struct net_device *netdev ) {
+ struct atl_nic *nic = netdev->priv;
+ uint32_t ctrl = 0;
+
+ /* Tx ring */
+ if ( atl_ring_alloc ( nic, &nic->tx_ring, sizeof ( struct atl_desc_tx ),
+ ATL_TX_DMA_DESC_ADDR ) != 0 )
+ goto err_tx_alloc;
+
+ /* Rx ring */
+ if ( atl_ring_alloc ( nic, &nic->rx_ring, sizeof ( struct atl_desc_rx ),
+ ATL_RX_DMA_DESC_ADDR ) != 0 )
+ goto err_rx_alloc;
+
+ /* Allocate interrupt vectors */
+ ATL_WRITE_REG ( ( ATL_IRQ_CTRL_COR_EN | ATL_IRQ_CTRL_REG_RST_DIS ),
+ ATL_IRQ_CTRL );
+
+ /*TX & RX Interruprt Mapping*/
+ ctrl = ATL_IRQ_MAP_REG1_RX0 | ATL_IRQ_MAP_REG1_RX0_EN |
+ ATL_IRQ_MAP_REG1_TX0 | ATL_IRQ_MAP_REG1_TX0_EN;
+ ATL_WRITE_REG ( ctrl, ATL_IRQ_MAP_REG1 );
+
+ /*TX interrupt ctrl reg*/
+ ATL_WRITE_REG ( ATL_TX_IRQ_CTRL_WB_EN, ATL_TX_IRQ_CTRL );
+
+ /*RX interrupt ctrl reg*/
+ ATL_WRITE_REG ( ATL_RX_IRQ_CTRL_WB_EN, ATL_RX_IRQ_CTRL );
+
+ /*RX data path*/
+ ctrl = ATL_IRQ_TX | ATL_IRQ_RX;
+ /* itr mask */
+ ATL_WRITE_REG ( ctrl, ATL_ITR_MSKS );
+ ATL_WRITE_REG ( ( uint32_t )ATL_RX_MAX_LEN / 1024U,
+ ATL_RX_DMA_DESC_BUF_SIZE );
+
+ /*filter global ctrl */
+ ctrl = ATL_RPF_CTRL1_BRC_EN | ATL_RPF_CTRL1_L2_PROMISC |
+ ATL_RPF_CTRL1_ACTION | ATL_RPF_CTRL1_BRC_TSH;
+ ATL_WRITE_REG ( ctrl, ATL_RPF_CTRL1 );
+
+ /* vlan promisc */
+ ATL_WRITE_REG ( ATL_RPF_CTRL2_VLAN_PROMISC, ATL_RPF_CTRL2 );
+ /* enable rpf2 */
+ ATL_WRITE_REG ( ATL_RPF2_CTRL_EN, ATL_RPF2_CTRL );
+
+ /* RX Packet Buffer 0 Register 1 */
+ ATL_WRITE_REG ( ATL_RPB0_CTRL1_SIZE, ATL_RPB0_CTRL1 );
+
+ /*RX Packet Buffer 0 Register 2 */
+ ctrl = ATL_RPB0_CTRL2_LOW_TSH | ATL_RPB0_CTRL2_HIGH_TSH |
+ ATL_RPB0_CTRL2_FC_EN;
+ ATL_WRITE_REG ( ctrl, ATL_RPB0_CTRL2 );
+
+ /*RPB global ctrl*/
+ ctrl = ATL_READ_REG ( ATL_RPB_CTRL );
+ ctrl |= ( ATL_RPB_CTRL_EN | ATL_RPB_CTRL_FC );
+ ATL_WRITE_REG ( ctrl, ATL_RPB_CTRL );
+
+ /*TX data path*/
+ /* enable tpo2 */
+ ATL_WRITE_REG ( ATL_TPO2_EN, ATL_TPO2_CTRL );
+ /* tpb global ctrl *** */
+ ATL_WRITE_REG ( ATL_TPB0_CTRL1_SIZE, ATL_TPB0_CTRL1 );
+
+ ctrl = ATL_TPB0_CTRL2_LOW_TSH | ATL_TPB0_CTRL2_HIGH_TSH;
+ /* tpb global ctrl *** */
+ ATL_WRITE_REG ( ctrl, ATL_TPB0_CTRL2 );
+
+ ctrl = ATL_READ_REG ( ATL_TPB_CTRL );
+ ctrl |= ( ATL_TPB_CTRL_EN | ATL_TPB_CTRL_PAD_EN );
+ /* tpb global ctrl */
+ ATL_WRITE_REG ( ctrl, ATL_TPB_CTRL );
+
+ /*Enable rings*/
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_RING_TX_CTRL ) | ATL_RING_TX_CTRL_EN,
+ ATL_RING_TX_CTRL );
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_RING_RX_CTRL ) | ATL_RING_RX_CTRL_EN,
+ ATL_RING_RX_CTRL );
+
+ if ( nic->flags == ATL_FLAG_A2 ) {
+ ATL_WRITE_REG ( ATL2_RPF_NEW_EN_ADR_EN, ATL2_RPF_NEW_EN_ADR );
+ }
+
+ atl_rx_ring_fill ( nic );
+
+ nic->hw_ops->start ( nic );
+
+ return 0;
+
+err_rx_alloc:
+ atl_ring_free ( &nic->tx_ring );
+
+err_tx_alloc:
+ return -ENOMEM;
+}
+
+/**
+* Close network device
+*
+* @v netdev Network device
+*/
+static void atl_close ( struct net_device *netdev ) {
+ struct atl_nic *nic = netdev->priv;
+
+ nic->hw_ops->stop ( nic );
+ /* rpb global ctrl */
+ ATL_WRITE_REG ( ATL_RPB_CTRL_DIS, ATL_RPB_CTRL );
+ /* tgb global ctrl */
+ ATL_WRITE_REG ( ATL_TPB_CTRL_DIS, ATL_TPB_CTRL);
+
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_RING_TX_CTRL ) | ( ~ATL_RING_TX_CTRL_EN ),
+ ATL_RING_TX_CTRL );
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_RING_RX_CTRL ) | ( ~ATL_RING_RX_CTRL_EN ),
+ ATL_RING_RX_CTRL );
+
+ /* clear itr mask */
+ ATL_WRITE_REG ( ATL_ITR_MSKS_DIS, ATL_ITR_MSKS );
+
+ /* Reset the NIC */
+ nic->hw_ops->reset ( nic );
+
+ atl_ring_free ( &nic->tx_ring );
+ atl_ring_free ( &nic->rx_ring );
+}
+
+/**
+* Transmit packet
+*
+* @v netdev Network device
+* @v iobuf I/O buffer
+* @ret rc Return status code
+*/
+int atl_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
+ struct atl_nic *nic = netdev->priv;
+ struct atl_desc_tx *tx;
+ physaddr_t address;
+ uint32_t len;
+
+ /* Get next transmit descriptor */
+ if ( atl_ring_full ( &nic->tx_ring ) ) {
+ DBGC ( nic, "AQUANTIA: %p out of transmit descriptors\n", nic );
+ return -ENOBUFS;
+ }
+
+ tx = ( struct atl_desc_tx * )nic->tx_ring.ring + nic->tx_ring.sw_tail;
+
+ /* Populate transmit descriptor */
+ memset ( tx, 0, sizeof ( *tx ) );
+ address = iob_dma ( iobuf );
+ tx->address = address;
+ len = iob_len ( iobuf );
+
+ tx->status = 0x1;
+ tx->status = ( (tx->status) & ~ATL_DESC_TX_BUF_LEN_MASK) |
+ ( (len << ATL_DESC_TX_BUF_LEN_OFFSET) &
+ ATL_DESC_TX_BUF_LEN_MASK );
+ tx->status = ((tx->status) & ~ATL_DESC_TX_EOP_MASK) |
+ ( (ATL_DESC_TX_DX_EOP_VALUE << ATL_DESC_TX_EOP_OFFSET) &
+ ATL_DESC_TX_EOP_MASK );
+ tx->status = ( (tx->status) & ~ATL_DESC_TX_CMD_MASK) |
+ ( (ATL_DESC_TX_CMD_VALUE << ATL_DESC_TX_CMD_OFFSET) &
+ ATL_DESC_TX_CMD_MASK );
+ tx->flag = ( (tx->flag) & ~ATL_DESC_TX_PAY_LEN_MASK) |
+ ( (len << ATL_DESC_TX_PAY_LEN_OFFSET) &
+ ATL_DESC_TX_PAY_LEN_MASK );
+ wmb();
+
+ DBGC2 ( nic, "AQUANTIA: %p TX[%d] is [%llx, %llx]\n",
+ nic, nic->tx_ring.sw_tail,
+ ( ( unsigned long long ) address ),
+ ( ( unsigned long long ) address + len ) );
+
+ atl_ring_next_dx ( &nic->tx_ring.sw_tail );
+ ATL_WRITE_REG ( nic->tx_ring.sw_tail, ATL_RING_TAIL );
+
+ return 0;
+}
+
+void atl_check_link ( struct net_device *netdev ) {
+ struct atl_nic *nic = netdev->priv;
+ uint32_t link_state;
+
+ /* Read link status */
+ link_state = nic->hw_ops->get_link ( nic );
+
+ DBGC ( nic, "AQUANTIA: %p link status is %08x\n", nic, link_state );
+
+ if ( link_state != nic->link_state ) {
+ if ( link_state ) {
+ DBGC ( nic, "AQUANTIA: link up\n");
+ netdev_link_up ( netdev );
+ } else {
+ DBGC ( nic, "AQUANTIA: link lost\n");
+ netdev_link_down ( netdev );
+ }
+ nic->link_state = link_state;
+ }
+}
+
+/**
+* Poll for completed packets
+*
+* @v netdev Network device
+*/
+void atl_poll_tx ( struct net_device *netdev ) {
+ struct atl_nic *nic = netdev->priv;
+ struct atl_desc_tx_wb *tx;
+
+ /* Check for completed packets */
+ while ( nic->tx_ring.sw_head != nic->tx_ring.sw_tail ) {
+
+ /* Get next transmit descriptor */
+ tx = ( struct atl_desc_tx_wb * )nic->tx_ring.ring +
+ nic->tx_ring.sw_head;
+
+ /* Stop if descriptor is still in use */
+ if ( !( tx->status & cpu_to_le32 ( ATL_TX_DESC_STATUS_DD ) ) )
+ return;
+
+ DBGC2 ( nic, "AQUANTIA: %p TX[%d] complete\n",
+ nic, nic->tx_ring.sw_head );
+
+ /* Complete TX descriptor */
+ atl_ring_next_dx ( &nic->tx_ring.sw_head );
+ netdev_tx_complete_next ( netdev );
+ }
+}
+
+/**
+* Poll for received packets
+*
+* @v netdev Network device
+*/
+void atl_poll_rx ( struct net_device *netdev ) {
+ struct atl_nic *nic = netdev->priv;
+ struct atl_desc_rx_wb *rx;
+ struct io_buffer *iobuf;
+ size_t len;
+
+ /* Check for received packets */
+ while ( nic->rx_ring.sw_head != nic->rx_ring.sw_tail ) {
+
+ /* Get next receive descriptor */
+ rx = ( struct atl_desc_rx_wb * )nic->rx_ring.ring +
+ nic->rx_ring.sw_head;
+
+ /* Stop if descriptor is still in use */
+ if ( !( rx->status & cpu_to_le16( ATL_RX_DESC_STATUS_DD ) ) )
+ return;
+
+ /* Populate I/O buffer */
+ iobuf = nic->iobufs[nic->rx_ring.sw_head];
+ nic->iobufs[nic->rx_ring.sw_head] = NULL;
+ len = le16_to_cpu ( rx->pkt_len );
+ iob_put ( iobuf, len );
+
+ /* Hand off to network stack */
+ DBGC ( nic, "AQUANTIA: %p RX[%d] complete (length %zd)\n",
+ nic, nic->rx_ring.sw_head, len );
+
+ netdev_rx ( netdev, iobuf );
+
+ atl_ring_next_dx ( &nic->rx_ring.sw_head );
+ }
+}
+
+/**
+* Poll for completed and received packets
+*
+* @v netdev Network device
+*/
+static void atl_poll ( struct net_device *netdev ) {
+ struct atl_nic *nic = netdev->priv;
+
+ /* Check link state */
+ atl_check_link ( netdev );
+
+ /* Poll for TX completions */
+ atl_poll_tx ( netdev );
+
+ /* Poll for RX completions */
+ atl_poll_rx ( netdev );
+
+ /* Refill RX ring */
+ atl_rx_ring_fill ( nic );
+}
+
+/**
+* Enable or disable interrupts
+*
+* @v netdev Network device
+* @v enable Interrupts should be enabled
+*/
+static void atl_irq ( struct net_device *netdev, int enable ) {
+ struct atl_nic *nic = netdev->priv;
+ uint32_t mask;
+
+ mask = ( ATL_IRQ_TX | ATL_IRQ_RX );
+ if ( enable )
+ ATL_WRITE_REG ( mask, ATL_ITR_MSKS );
+ else
+ ATL_WRITE_REG ( mask, ATL_ITR_MSKC );
+}
+
+/** Marvell network device operations */
+static struct net_device_operations atl_operations = {
+ .open = atl_open,
+ .close = atl_close,
+ .transmit = atl_transmit,
+ .poll = atl_poll,
+ .irq = atl_irq,
+};
+
+/******************************************************************************
+*
+* PCI interface
+*
+*******************************************************************************
+*/
+
+/**
+* Probe PCI device
+*
+* @v pci PCI device
+* @ret rc Return status code
+*/
+static int atl_probe ( struct pci_device *pci ) {
+ struct net_device *netdev;
+ struct atl_nic *nic;
+ int rc = ENOERR;
+ uint32_t io_size = 0;
+
+ /* Allocate and initialise net device */
+ netdev = alloc_etherdev ( sizeof( *nic ) );
+ if ( !netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ netdev_init ( netdev, &atl_operations );
+ nic = netdev->priv;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ memset( nic, 0, sizeof ( *nic ) );
+ nic->flags = pci->id->driver_data;
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ switch ( nic->flags ) {
+ case ATL_FLAG_A1:
+ nic->hw_ops = &atl_hw;
+ io_size = ATL_BAR_SIZE;
+ break;
+ case ATL_FLAG_A2:
+ nic->hw_ops = &atl2_hw;
+ io_size = ATL2_BAR_SIZE;
+ break;
+ default:
+ goto err_unsupported;
+ break;
+ }
+
+ /* Map registers */
+ nic->regs = pci_ioremap ( pci, pci->membase, io_size );
+ if ( !nic->regs ) {
+ rc = -ENODEV;
+ goto err_ioremap;
+ }
+
+ /* Configure DMA */
+ nic->dma = &pci->dma;
+
+ /* Reset the NIC */
+ if ( ( rc = nic->hw_ops->reset ( nic ) ) != 0 )
+ goto err_reset;
+
+ /* Get MAC Address */
+ if ( ( rc = nic->hw_ops->get_mac ( nic, netdev->hw_addr ) ) != 0 )
+ goto err_mac;
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ /* Set initial link state */
+ netdev_link_down ( netdev );
+
+ return 0;
+
+err_register_netdev:
+err_mac:
+ nic->hw_ops->reset ( nic );
+err_reset:
+ iounmap ( nic->regs );
+err_ioremap:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+err_unsupported:
+err_alloc:
+ return rc;
+}
+
+/**
+* Remove PCI device
+*
+* @v pci PCI device
+*/
+static void atl_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct atl_nic *nic = netdev->priv;
+
+ /* Unregister network device */
+ unregister_netdev ( netdev );
+
+ /* Reset the NIC */
+ nic->hw_ops->reset ( nic );
+
+ /* Free network device */
+ iounmap ( nic->regs );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** Marvell PCI device IDs */
+static struct pci_device_id atl_nics[] = {
+ /* Atlantic 1 */
+ /* 10G */
+ PCI_ROM ( 0x1D6A, 0x0001, "AQC07", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0xD107, "AQC07", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x07B1, "AQC07", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x87B1, "AQC07", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A1 ),
+
+ /* SFP */
+ PCI_ROM ( 0x1D6A, 0xD100, "AQC00", "Felicity Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x00B1, "AQC00", "Felicity Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x80B1, "AQC00", "Felicity Network Adapter", ATL_FLAG_A1 ),
+
+ /* 5G */
+ PCI_ROM ( 0x1D6A, 0xD108, "AQC08", "Marvell AQtion 5Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x08B1, "AQC08", "Marvell AQtion 5Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x88B1, "AQC08", "Marvell AQtion 5Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x11B1, "AQC11", "Marvell AQtion 5Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x91B1, "AQC11", "Marvell AQtion 5Gbit Network Adapter", ATL_FLAG_A1 ),
+
+ /* 2.5G */
+ PCI_ROM ( 0x1D6A, 0xD109, "AQC09", "Marvell AQtion 2.5Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x09B1, "AQC09", "Marvell AQtion 2.5Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x89B1, "AQC09", "Marvell AQtion 2.5Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x12B1, "AQC12", "Marvell AQtion 2.5Gbit Network Adapter", ATL_FLAG_A1 ),
+ PCI_ROM ( 0x1D6A, 0x92B1, "AQC12", "Marvell AQtion 2.5Gbit Network Adapter", ATL_FLAG_A1 ),
+
+ /* Atlantic 2 */
+ PCI_ROM ( 0x1D6A, 0x00C0, "AQC13", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A2 ),
+ PCI_ROM ( 0x1D6A, 0x94C0, "AQC13", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A2 ),
+ PCI_ROM ( 0x1D6A, 0x93C0, "AQC13", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A2 ),
+ PCI_ROM ( 0x1D6A, 0x04C0, "AQC13", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A2 ),
+ PCI_ROM ( 0x1D6A, 0x14C0, "AQC13", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A2 ),
+ PCI_ROM ( 0x1D6A, 0x12C0, "AQC13", "Marvell AQtion 10Gbit Network Adapter", ATL_FLAG_A2 ),
+ PCI_ROM ( 0x1D6A, 0x03C0, "AQC14", "Marvell AQtion 5Gbit Network Adapter", ATL_FLAG_A2 ),
+};
+
+/** Marvell PCI driver */
+struct pci_driver atl_driver __pci_driver = {
+ .ids = atl_nics,
+ .id_count = ( sizeof( atl_nics ) / sizeof ( atl_nics[0] ) ),
+ .probe = atl_probe,
+ .remove = atl_remove,
+};
diff --git a/src/drivers/net/marvell/aqc1xx.h b/src/drivers/net/marvell/aqc1xx.h
new file mode 100644
index 0000000..26bdd00
--- /dev/null
+++ b/src/drivers/net/marvell/aqc1xx.h
@@ -0,0 +1,270 @@
+/** @file
+ *
+ * Marvell AQtion family network card driver definitions.
+ *
+ * Copyright(C) 2017-2024 Marvell
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef _ATLANTIC_H
+#define _ATLANTIC_H
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/nvs.h>
+
+#define ATL_BAR_SIZE 0x10000
+#define ATL2_BAR_SIZE 0x40000
+#define ATL_RING_SIZE 64
+#define ATL_RING_ALIGN 128
+#define ATL_RX_MAX_LEN 2048
+
+#define ATL_IRQ_TX 0x00000001U
+#define ATL_IRQ_RX 0x00000002U
+
+/*IRQ Status Register*/
+#define ATL_IRQ_STAT_REG 0x00002000U
+
+/* Interrupt Vector Allocation Register */
+#define ATL_IRQ_CTRL 0x00002300U
+#define ATL_IRQ_CTRL_COR_EN 0x00000080U /*IRQ clear on read */
+#define ATL_IRQ_CTRL_REG_RST_DIS 0x20000000U /*Register reset disable */
+
+/*TX/RX Interruprt Mapping*/
+#define ATL_IRQ_MAP_REG1 0x00002100U /*IRQ mapping register */
+
+#define ATL_IRQ_MAP_REG1_RX0_EN 0x00008000U /*IRQ RX0 enable*/
+#define ATL_IRQ_MAP_REG1_RX0 0x00000100U /*IRQ RX0*/
+
+#define ATL_IRQ_MAP_REG1_TX0_EN 0x80000000U /*IRQ TX0 enable*/
+#define ATL_IRQ_MAP_REG1_TX0 0x00000000U /*IRQ TX0*/
+
+/*TX interrupt ctrl reg*/
+#define ATL_TX_IRQ_CTRL 0x00007B40U
+#define ATL_TX_IRQ_CTRL_WB_EN 0x00000002U
+
+/*RX interrupt ctrl reg*/
+#define ATL_RX_IRQ_CTRL 0x00005A30U
+#define ATL_RX_IRQ_CTRL_WB_EN 0x00000004U
+
+#define ATL_GLB_CTRL 0x00000000U
+
+#define ATL_PCI_CTRL 0x00001000U
+#define ATL_PCI_CTRL_RST_DIS 0x20000000U
+
+#define ATL_RX_CTRL 0x00005000U
+#define ATL_RX_CTRL_RST_DIS 0x20000000U /*RPB reset disable */
+#define ATL_TX_CTRL 0x00007000U
+#define ATL_TX_CTRL_RST_DIS 0x20000000U /*TPB reset disable */
+
+/*RX data path control registers*/
+#define ATL_RPF2_CTRL 0x00005040U
+#define ATL_RPF2_CTRL_EN 0x000F0000U /* RPF2 enable*/
+#define ATL2_RPF_NEW_EN_ADR_EN 0x00000001U /*enable*/
+#define ATL2_RPF_NEW_EN_ADR 0x5104
+
+#define ATL_RPF_CTRL1 0x00005100U
+#define ATL_RPF_CTRL1_BRC_EN 0x00000001U /*Allow broadcast receive*/
+#define ATL_RPF_CTRL1_L2_PROMISC 0x00000008U /*L2 promiscious*/
+#define ATL_RPF_CTRL1_ACTION 0x00001000U /*Action to host*/
+#define ATL_RPF_CTRL1_BRC_TSH 0x00010000U /*Brc threshold 256 units per sec*/
+
+#define ATL_RPF_CTRL2 0x00005280U
+#define ATL_RPF_CTRL2_VLAN_PROMISC 0x00000002U /*VLAN promisc*/
+
+#define ATL_RPB_CTRL_DIS 0x0
+#define ATL_RPB_CTRL 0x00005700U
+#define ATL_RPB_CTRL_EN 0x00000001U /*RPB Enable*/
+#define ATL_RPB_CTRL_FC 0x00000010U /*RPB Enable*/
+#define ATL_RPB_CTRL_TC_MODE 0x00000100U /*RPB Traffic Class Mode*/
+
+#define ATL_RPB0_CTRL1 0x00005710U
+#define ATL_RPB0_CTRL1_SIZE 0x00000140U /*RPB size (in unit 1KB) \*/
+
+#define ATL_RPB0_CTRL2 0x00005714U
+
+/*Buffer Low Threshold (70% of RPB size in unit 32B)*/
+#define ATL_RPB0_CTRL2_LOW_TSH 0x00000C00U
+/*Buffer High Threshold(30% of RPB size in unit 32B)*/
+#define ATL_RPB0_CTRL2_HIGH_TSH 0x1C000000U
+#define ATL_RPB0_CTRL2_FC_EN 0x80000000U /*Flow control Enable*/
+
+#define ATL_RX_DMA_DESC_BUF_SIZE 0x00005b18U
+#define ATL_RX_DMA_DESC_ADDR 0x00005b00U
+
+/*TX data path control registers*/
+#define ATL_TPO2_CTRL 0x00007040U
+#define ATL_TPO2_EN 0x00010000U /*TPO2 Enable*/
+
+#define ATL_TPB_CTRL_DIS 0x0
+#define ATL_TPB_CTRL 0x00007900U
+#define ATL_TPB_CTRL_EN 0x00000001U /*TPB enable*/
+#define ATL_TPB_CTRL_PAD_EN 0x00000004U /*Tx pad insert enable*/
+#define ATL_TPB_CTRL_TC_MODE 0x00000100U /*Tx traffic Class Mode*/
+
+#define ATL_TPB0_CTRL1 0x00007910U
+#define ATL_TPB0_CTRL1_SIZE 0x000000A0U /*TPB Size (in unit 1KB)*/
+
+#define ATL_TPB0_CTRL2 0x00007914U
+/*Buffer Low Threshold(30% of RPB size in unit 32B)*/
+#define ATL_TPB0_CTRL2_LOW_TSH 0x00000600U
+/*Buffer High Threshold(30% of RPB size in unit 32B)*/
+#define ATL_TPB0_CTRL2_HIGH_TSH 0x0E000000U
+
+#define ATL_TX_DMA_DESC_ADDR 0x00007c00U
+
+/*Rings control registers*/
+#define ATL_RING_TX_CTRL 0x00007c08U
+#define ATL_RING_TX_CTRL_EN 0x80000000U /*Tx descriptor Enable*/
+
+#define ATL_RING_RX_CTRL 0x00005b08U
+#define ATL_RING_RX_CTRL_EN 0x80000000U /*Rx descriptor Enable*/
+
+#define ATL_RING_TAIL 0x00007c10U
+#define ATL_RING_TAIL_PTR 0x00005b10U
+
+/*IRQ control registers*/
+#define ATL_ITR_MSKS_DIS 0x0
+#define ATL_ITR_MSKS 0x00002060U
+#define ATL_ITR_MSKS_LSW 0x0000000CU
+#define ATL_ITR_MSKC 0x00002070U
+#define ATL_ITR_MSKC_LSW 0x0000000CU
+
+/*Link advertising*/
+#define ATL_LINK_ADV 0x00000368U
+#define ATL_SHUT_LINK 0x0
+#define ATL_LINK_ADV_AUTONEG 0xF20U
+
+#define ATL_LINK_ST 0x00000370U
+
+/*Semaphores*/
+#define ATL_SEM_RAM 0x000003a8U
+#define ATL_SEM_RAM_RESET 0X1
+
+/*Mailbox*/
+#define ATL_MBOX_ADDR 0x00000360U
+#define ATL_MBOX_CTRL1 0x00000200U
+#define ATL_MBOX_CTRL1_START_MBOX_OPT 0x8000
+
+#define ATL_MBOX_CTRL3 0x00000208U
+#define ATL_MBOX_CTRL5 0x0000020cU
+
+#define ATL_FLAG_A1 0x1
+#define ATL_FLAG_A2 0x2
+
+/*write register*/
+#define ATL_WRITE_REG( VAL, REG ) writel( VAL, nic->regs + (REG) )
+#define ATL_READ_REG( REG ) readl( nic->regs + (REG) ) /*read register*/
+
+struct atl_desc_tx {
+ uint64_t address;
+ uint32_t status;
+ uint32_t flag;
+} __attribute__ (( packed ));
+
+#define ATL_DESC_TX_DX_TYPE_VALUE 0x1
+
+#define ATL_DESC_TX_DX_EOP_VALUE 0x1
+#define ATL_DESC_TX_EOP_MASK 0x00200000
+#define ATL_DESC_TX_EOP_OFFSET 21
+
+#define ATL_DESC_TX_CMD_MASK 0x3FC00000UL
+#define ATL_DESC_TX_CMD_OFFSET 22
+#define ATL_DESC_TX_CMD_VALUE 0x22
+
+#define ATL_DESC_TX_BUF_LEN_MASK 0x000FFFF0
+#define ATL_DESC_TX_BUF_LEN_OFFSET 5
+
+#define ATL_DESC_TX_PAY_LEN_MASK 0xFFFFC000
+#define ATL_DESC_TX_PAY_LEN_OFFSET 14
+
+struct atl_desc_tx_wb {
+ uint64_t rsvd1;
+ uint32_t status;
+ uint32_t rsvd4;
+} __attribute__ (( packed ));
+
+#define ATL_TX_DESC_STATUS_DD 0x00100000UL
+
+struct atl_desc_rx {
+ uint64_t data_addr;
+ uint64_t hdr_addr;
+
+} __attribute__ (( packed ));
+
+struct atl_desc_rx_wb {
+ uint64_t rsvd2;
+ uint16_t status;
+ uint16_t pkt_len;
+ uint32_t rsvd4;
+} __attribute__ (( packed ));
+
+#define ATL_RX_DESC_STATUS_DD 0x0001UL
+#define ATL_RX_DESC_STATUS_EOP 0x0002UL
+struct atl_ring {
+ unsigned int sw_tail;
+ unsigned int sw_head;
+ void *ring;
+ /** Descriptor ring DMA mapping */
+ struct dma_mapping map;
+ unsigned int length;
+};
+
+struct atl_nic;
+
+struct atl_hw_ops {
+ int ( *reset ) ( struct atl_nic *nic );
+ int ( *start ) ( struct atl_nic *nic );
+ int ( *stop ) ( struct atl_nic *nic );
+ int ( *get_link ) ( struct atl_nic *nic );
+ int ( *get_mac ) ( struct atl_nic *, uint8_t *mac );
+};
+
+/** An aQuanita network card */
+struct atl_nic {
+ /** Registers */
+ void *regs;
+ /** Port number (for multi-port devices) */
+ unsigned int port;
+ /** DMA device */
+ struct dma_device *dma;
+ /** Flags */
+ unsigned int flags;
+ struct atl_ring tx_ring;
+ struct atl_ring rx_ring;
+ struct io_buffer *iobufs[ATL_RING_SIZE];
+ uint32_t link_state;
+ uint32_t mbox_addr;
+ struct atl_hw_ops *hw_ops;
+};
+
+struct atl_hw_stats {
+ uint32_t version;
+ uint32_t tid;
+};
+
+#endif /* _AQUANTIA_H */
diff --git a/src/drivers/net/marvell/atl2_hw.c b/src/drivers/net/marvell/atl2_hw.c
new file mode 100644
index 0000000..8058207
--- /dev/null
+++ b/src/drivers/net/marvell/atl2_hw.c
@@ -0,0 +1,225 @@
+/** @file
+ *
+ * Marvell AQtion family network card driver, hardware-specific functions.
+ *
+ * Copyright(C) 2017-2024 Marvell
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO,THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include "aqc1xx.h"
+#include "atl2_hw.h"
+
+static int atl2_hw_boot_completed_ ( struct atl_nic *nic ) {
+ uint32_t reset_status = ATL_READ_REG ( ATL2_GLB_RST_CTRL2 );
+
+ return ( reset_status & ATL2_RESET_STATUS_BOOT_COMPLETED_MASK ) ||
+ ( ATL_READ_REG ( ATL2_HOST_ITR_REQ )
+ & ATL2_FW_HOST_INTERRUPT_REQUEST_READY );
+}
+
+void atl2_hw_read_shared_in_ ( struct atl_nic *nic, uint32_t offset,
+ uint32_t *data, uint32_t len ) {
+ uint32_t i;
+
+ for (i = 0; i < len; ++i )
+ {
+ data[i] = ATL_READ_REG ( ATL2_MIF_SHARED_BUF_IN + offset + i * 4 );
+ }
+}
+
+void atl2_hw_write_shared_in_ ( struct atl_nic *nic, uint32_t offset,
+ uint32_t *data, uint32_t len ) {
+ uint32_t i;
+
+ for ( i = 0; i < len; ++i )
+ {
+ ATL_WRITE_REG ( data[i], ATL2_MIF_SHARED_BUF_IN + offset + i * 4 );
+ }
+}
+
+int atl2_hw_finish_ack_ ( struct atl_nic *nic, uint32_t ms ) {
+ uint32_t i;
+ int err = 0;
+
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL2_HOST_FINISHED_WRITE )
+ | 1, ATL2_HOST_FINISHED_WRITE );
+
+ for ( i = 0; i < ( ms / 100 ); ++i )
+ {
+ if ( ( ATL_READ_REG ( ATL2_MCP_BUSY_WRITE ) & 1 ) == 0 )
+ {
+ break;
+ }
+ udelay ( ATL2_DELAY_100 );
+ }
+ if (i == ( ms / 100 ) )
+ err = -ETIME;
+
+ return err;
+}
+
+int atl2_hw_fw_init_ ( struct atl_nic *nic ) {
+ uint32_t val;
+ int err = 0;
+
+ atl2_hw_read_shared_in_ ( nic, ATL2_LINK_CTRL_IN_OFF, &val, 1 );
+ val |= ( ATL2_HOST_MODE_ACTIVE | ( 1U << 13 ) );
+ atl2_hw_write_shared_in_ ( nic, ATL2_LINK_CTRL_IN_OFF, &val, 1 );
+
+ atl2_hw_read_shared_in_ ( nic, ATL2_MTU_IN_OFF, &val, 1 );
+ val = 16352;
+ atl2_hw_write_shared_in_ ( nic, ATL2_MTU_IN_OFF, &val, 1 );
+
+ atl2_hw_read_shared_in_ ( nic, ATL2_LINK_OPTS_IN_OFF, &val, 1 );
+ val = 0;
+ atl2_hw_write_shared_in_( nic, ATL2_LINK_OPTS_IN_OFF, &val, 1 );
+ err = atl2_hw_finish_ack_ ( nic, 50000000 );
+
+ return err;
+}
+
+int atl2_hw_reset ( struct atl_nic *nic ) {
+ int completed = 0;
+ uint32_t status = 0;
+ uint32_t request;
+ int err = 0;
+ int i;
+
+ request = ATL2_RESET_STATUS_REQ_GSR;
+
+ ATL_WRITE_REG ( request, ATL2_GLB_RST_CTRL2 );
+
+ /* Wait for boot code started every 10us, 200 ms */
+ for ( i = 0; i < 20000; ++i )
+ {
+ status = ATL_READ_REG ( ATL2_GLB_RST_CTRL2 );
+
+ if ( ( ( status & ATL2_RESET_STATUS_BC_STARTED ) &&
+ ( status != 0xFFFFFFFFu ) ) )
+ break;
+
+ udelay ( ATL2_DELAY_10 );
+ }
+ if ( i == 20000 )
+ {
+ DBGC ( nic, "Boot code hanged" );
+ err = -EIO;
+ goto err_exit;
+ }
+
+ /* Wait for boot succeed, failed or host request every 10us, 480ms */
+ for ( i = 0; i < 48000; ++i )
+ {
+ completed = atl2_hw_boot_completed_ ( nic );
+ if ( completed )
+ break;
+
+ udelay ( ATL2_DELAY_10 );
+ }
+
+ if ( !completed )
+ {
+ DBGC ( nic, "FW Restart timed out" );
+ err = -ETIME;
+ goto err_exit;
+ }
+
+ status = ATL_READ_REG ( ATL2_GLB_RST_CTRL2 );
+
+ if ( status & ATL2_RESET_STATUS_BOOT_FAILED_MASK )
+ {
+ err = -EIO;
+ DBGC ( nic, "FW Restart failed" );
+ DBGC ( nic, "status = 0x%x", status );
+ goto err_exit;
+ }
+
+ if ( ATL_READ_REG ( ATL2_HOST_ITR_REQ )
+ & ATL2_FW_HOST_INTERRUPT_REQUEST_READY )
+ {
+ err = -ENOTSUP;
+ DBGC ( nic, "Dynamic FW load not implemented" );
+ goto err_exit;
+ }
+
+ err = atl2_hw_fw_init_ ( nic );
+
+err_exit:
+ return err;
+}
+
+int atl2_hw_start ( struct atl_nic *nic ) {
+ uint32_t val;
+
+ atl2_hw_read_shared_in_ ( nic, ATL2_LINK_OPTS_IN_OFF, &val, 1 );
+ val = 0x4B00FFE1;
+ atl2_hw_write_shared_in_ ( nic, ATL2_LINK_OPTS_IN_OFF, &val, 1 );
+
+ return atl2_hw_finish_ack_ ( nic, 100000 );
+}
+
+int atl2_hw_stop ( struct atl_nic *nic ) {
+ uint32_t val;
+
+ atl2_hw_read_shared_in_ ( nic, ATL2_LINK_OPTS_IN_OFF, &val, 1 );
+ val = 0;
+ atl2_hw_write_shared_in_ ( nic, ATL2_LINK_OPTS_IN_OFF, &val, 1 );
+
+ return atl2_hw_finish_ack_ ( nic, 100000 );
+}
+
+int atl2_hw_get_link ( struct atl_nic *nic ) {
+ uint32_t val;
+
+ val = ATL_READ_REG ( ATL2_MIF_SHARED_BUF_OUT + ATL2_LINK_STS_OUT_OFF );
+
+ return ( ( val & 0xf ) != 0 ) && ( ( val & 0xF0 ) != 0 );
+}
+
+int atl2_hw_get_mac ( struct atl_nic *nic, uint8_t *mac ) {
+ uint32_t mac_addr[2] = {0};
+
+ atl2_hw_read_shared_in_ ( nic, ATL2_MAC_ADDR_IN_OFF, mac_addr, 2 );
+
+ memcpy ( mac, ( uint8_t * )mac_addr, 6 );
+
+ return 0;
+}
+
+struct atl_hw_ops atl2_hw = {
+ .reset = atl2_hw_reset,
+ .start = atl2_hw_start,
+ .stop = atl2_hw_stop,
+ .get_link = atl2_hw_get_link,
+ .get_mac = atl2_hw_get_mac,
+};
diff --git a/src/drivers/net/marvell/atl2_hw.h b/src/drivers/net/marvell/atl2_hw.h
new file mode 100644
index 0000000..d044c21
--- /dev/null
+++ b/src/drivers/net/marvell/atl2_hw.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright(C) 2017-2024 Marvell
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO,THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __ATL2_HW_H
+#define __ATL2_HW_H
+
+FILE_LICENCE ( BSD2 );
+
+#define ATL2_GLB_RST_CTRL2 0x3040
+#define ATL2_HOST_FINISHED_WRITE 0xE00
+#define ATL2_MCP_BUSY_WRITE 0xE04
+#define ATL2_HOST_ITR_REQ 0xF00
+
+
+#define ATL2_RESET_STATUS_REQ_GSR ( 1U << 0x0 )
+#define ATL2_RESET_STATUS_REQ_HOST_BOOT ( 1U << 0x8 )
+#define ATL2_RESET_STATUS_REQ_MAC_FAST_BOOT ( 1U << 0xA )
+#define ATL2_RESET_STATUS_REQ_PHY_FAST_BOOT ( 1U << 0xB )
+
+#define ATL2_RESET_STATUS_HOST_LOAD_COMPLETED ( 1U << 0x10 )
+#define ATL2_RESET_STATUS_REQUIRE_HOST_LOAD ( 1U << 0x11 )
+#define ATL2_RESET_STATUS_BC_STARTED ( 1U << 0x18 )
+#define ATL2_RESET_STATUS_CRASH_DURING_INIT ( 1U << 0x1B )
+#define ATL2_RESET_STATUS_BC_FAILED ( 1U << 0x1C )
+#define ATL2_RESET_STATUS_FW_FAILED ( 1U << 0x1D )
+#define ATL2_RESET_STATUS_FW_SUCCEED ( 1U << 0x1F )
+
+#define ATL2_RESET_STATUS_BOOT_FAILED_MASK ( ATL2_RESET_STATUS_CRASH_DURING_INIT | ATL2_RESET_STATUS_BC_FAILED | ATL2_RESET_STATUS_FW_FAILED )
+#define ATL2_RESET_STATUS_BOOT_COMPLETED_MASK ( ATL2_RESET_STATUS_BOOT_FAILED_MASK | ATL2_RESET_STATUS_FW_SUCCEED )
+
+#define ATL2_FW_HOST_INTERRUPT_REQUEST_READY 0x0001
+#define ATL2_FW_HOST_INTERRUPT_MAC_READY 0x0004
+#define ATL2_FW_HOST_INTERRUPT_DATA_HANDLED 0x0100
+#define ATL2_FW_HOST_INTERRUPT_LINK_UP 0x0200
+#define ATL2_FW_HOST_INTERRUPT_LINK_DOWN 0x0400
+#define ATL2_FW_HOST_INTERRUPT_PHY_FAULT 0x0800
+#define ATL2_FW_HOST_INTERRUPT_MAC_FAULT 0x1000
+#define ATL2_FW_HOST_INTERRUPT_TEMPERATURE_WARNING 0x2000
+#define ATL2_FW_HOST_INTERRUPT_HEARTBEAT 0x4000
+
+#define ATL2_FW_LINK_RATE_INVALID 0
+#define ATL2_FW_LINK_RATE_10M 1
+#define ATL2_FW_LINK_RATE_100M 2
+#define ATL2_FW_LINK_RATE_1G 3
+#define ATL2_FW_LINK_RATE_2G5 4
+#define ATL2_FW_LINK_RATE_5G 5
+#define ATL2_FW_LINK_RATE_10G 6
+
+#define ATL2_HOST_MODE_INVALID 0U
+#define ATL2_HOST_MODE_ACTIVE 1U
+#define ATL2_HOST_MODE_SLEEP_PROXY 2U
+#define ATL2_HOST_MODE_LOW_POWER 3U
+#define ATL2_HOST_MODE_SHUTDOWN 4U
+
+#define ATL2_MIF_SHARED_BUF_IN 0x12000
+#define ATL2_MIF_SHARED_BUF_OUT 0x13000
+
+#define ATL2_MTU_IN_OFF 0x0
+#define ATL2_MAC_ADDR_IN_OFF 0x8
+#define ATL2_LINK_CTRL_IN_OFF 0x10
+#define ATL2_LINK_OPTS_IN_OFF 0x18
+
+#define ATL2_FW_OUT_OFF 0x8
+#define ATL2_LINK_STS_OUT_OFF 0x14
+
+#define ATL2_DELAY_10 10
+#define ATL2_DELAY_100 100
+
+#endif
diff --git a/src/drivers/net/marvell/atl_hw.c b/src/drivers/net/marvell/atl_hw.c
new file mode 100644
index 0000000..e0843e6
--- /dev/null
+++ b/src/drivers/net/marvell/atl_hw.c
@@ -0,0 +1,313 @@
+/** @file
+ *
+ * Marvell AQtion family network card driver, hardware-specific functions.
+ *
+ * Copyright(C) 2017-2024 Marvell
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO,THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include "aqc1xx.h"
+#include "atl_hw.h"
+#include <compiler.h>
+
+
+int atl_hw_reset_flb_ ( struct atl_nic *nic ) {
+ uint32_t val;
+ int k = 0;
+
+ ATL_WRITE_REG ( ATL_GLB_CTRL2_MBOX_ERR_UP_RUN_STALL, ATL_GLB_CTRL2 );
+ mdelay ( ATL_DELAY_50_MNS );
+
+ /* Cleanup SPI */
+ val = ATL_READ_REG ( ATL_GLB_NVR_PROV4 );
+ ATL_WRITE_REG ( val | ATL_GBL_NVR_PROV4_RESET, ATL_GLB_NVR_PROV4 );
+
+ ATL_WRITE_REG( ( ATL_READ_REG ( ATL_GLB_STD_CTRL ) &
+ ~ATL_GLB_CTRL_RST_DIS ) | ATL_GLB_STD_CTRL_RESET,
+ ATL_GLB_STD_CTRL );
+
+ /* Kickstart MAC */
+ ATL_WRITE_REG ( ATL_GLB_CTRL2_FW_RESET, ATL_GLB_CTRL2 );
+ ATL_WRITE_REG ( ATL_MIF_PWR_GATING_EN_CTRL_RESET,
+ ATL_MIF_PWR_GATING_EN_CTRL );
+
+ ATL_WRITE_REG ( ATL_GEN_PROV9_ENABLE, ATL_GEN_PROV9 );
+
+ /* Reset SPI again because of possible interrupted SPI burst */
+ val = ATL_READ_REG ( ATL_GLB_NVR_PROV4 );
+ ATL_WRITE_REG ( val | ATL_GBL_NVR_PROV4_RESET, ATL_GLB_NVR_PROV4 );
+ mdelay ( ATL_DELAY_10_MNS );
+ /* Clear SPI reset state */
+ ATL_WRITE_REG ( val & ~ATL_GBL_NVR_PROV4_RESET, ATL_GLB_NVR_PROV4 );
+
+ /* MAC Kickstart */
+ ATL_WRITE_REG ( ATL_GLB_CTRL2_MAC_KICK_START, ATL_GLB_CTRL2 );
+
+ for (k = 0; k < 1000; k++) {
+ uint32_t flb_status = ATL_READ_REG ( ATL_MPI_DAISY_CHAIN_STS );
+
+ flb_status = flb_status & FLB_LOAD_STS;
+ if ( flb_status )
+ break;
+ mdelay ( ATL_DELAY_10_MNS );
+ }
+ if ( k == 1000 ) {
+ DBGC (nic, "MAC kickstart failed\n" );
+ return -EIO;
+ }
+
+ /* FW reset */
+ ATL_WRITE_REG ( ATL_GLB_CTRL2_FW_RESET, ATL_GLB_CTRL2 );
+ mdelay ( ATL_DELAY_50_MNS );
+
+ ATL_WRITE_REG ( ATL_GBL_MCP_SEM1_RELEASE, ATL_GLB_MCP_SEM1 );
+
+ /* Global software reset*/
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_RX_CTRL ) &
+ ~ATL_RX_CTRL_RST_DIS, ATL_RX_CTRL );
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_TX_CTRL ) &
+ ~ATL_TX_CTRL_RST_DIS, ATL_TX_CTRL );
+
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_MAC_PHY_CTRL ) &
+ ~ATL_MAC_PHY_CTRL_RST_DIS, ATL_MAC_PHY_CTRL );
+
+ ATL_WRITE_REG ( ( ATL_READ_REG ( ATL_GLB_STD_CTRL ) &
+ ~ATL_GLB_CTRL_RST_DIS ) | ATL_GLB_STD_CTRL_RESET,
+ ATL_GLB_STD_CTRL );
+
+ for (k = 0; k < 1000; k++) {
+ u32 fw_state = ATL_READ_REG ( ATL_FW_VER );
+
+ if ( fw_state )
+ break;
+ mdelay ( ATL_DELAY_10_MNS );
+ }
+ if ( k == 1000 ) {
+ DBGC ( nic, "FW kickstart failed\n" );
+ return -EIO;
+ }
+ /* Old FW requires fixed delay after init */
+ mdelay ( ATL_DELAY_15_MNS );
+
+ return 0;
+}
+
+int atl_hw_reset_rbl_ ( struct atl_nic *nic ) {
+ uint32_t val, rbl_status;
+ int k;
+
+ ATL_WRITE_REG ( ATL_GLB_CTRL2_MBOX_ERR_UP_RUN_STALL, ATL_GLB_CTRL2 );
+ ATL_WRITE_REG ( ATL_GBL_MCP_SEM1_RELEASE, ATL_GLB_MCP_SEM1 );
+ ATL_WRITE_REG ( ATL_MIF_PWR_GATING_EN_CTRL_RESET,
+ ATL_MIF_PWR_GATING_EN_CTRL );
+
+ /* Alter RBL status */
+ ATL_WRITE_REG ( POISON_SIGN, ATL_MPI_BOOT_EXIT_CODE );
+
+ /* Cleanup SPI */
+ val = ATL_READ_REG ( ATL_GLB_NVR_PROV4 );
+ ATL_WRITE_REG ( val | ATL_GBL_NVR_PROV4_RESET, ATL_GLB_NVR_PROV4 );
+
+ /* Global software reset*/
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_RX_CTRL ) & ~ATL_RX_CTRL_RST_DIS,
+ ATL_RX_CTRL );
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_TX_CTRL ) & ~ATL_TX_CTRL_RST_DIS,
+ ATL_TX_CTRL );
+ ATL_WRITE_REG ( ATL_READ_REG ( ATL_MAC_PHY_CTRL ) &
+ ~ATL_MAC_PHY_CTRL_RST_DIS, ATL_MAC_PHY_CTRL );
+
+ ATL_WRITE_REG ( ( ATL_READ_REG ( ATL_GLB_STD_CTRL ) &
+ ~ATL_GLB_CTRL_RST_DIS ) | ATL_GLB_STD_CTRL_RESET,
+ ATL_GLB_STD_CTRL );
+
+ ATL_WRITE_REG ( ATL_GLB_CTRL2_MBOX_ERR_UP_RUN_NORMAL, ATL_GLB_CTRL2 );
+
+ /* Wait for RBL boot */
+ for ( k = 0; k < 1000; k++ ) {
+ rbl_status = ATL_READ_REG ( ATL_MPI_BOOT_EXIT_CODE ) & 0xFFFF;
+ if ( rbl_status && rbl_status != POISON_SIGN )
+ break;
+ mdelay ( ATL_DELAY_10_MNS );
+ }
+ if ( !rbl_status || rbl_status == POISON_SIGN ) {
+ DBGC ( nic, "RBL Restart failed\n" );
+ return -EIO;
+ }
+
+ if ( rbl_status == FW_NOT_SUPPORT )
+ return -ENOTSUP;
+
+ for ( k = 0; k < 1000; k++ ) {
+ u32 fw_state = ATL_READ_REG ( ATL_FW_VER );
+
+ if ( fw_state )
+ break;
+ mdelay ( ATL_DELAY_10_MNS );
+ }
+ if ( k == 1000 ) {
+ DBGC ( nic, "FW kickstart failed\n" );
+ return -EIO;
+ }
+ /* Old FW requires fixed delay after init */
+ mdelay ( ATL_DELAY_15_MNS );
+
+ return 0;
+}
+
+int atl_hw_reset ( struct atl_nic *nic ) {
+ uint32_t boot_exit_code = 0;
+ uint32_t k;
+ int rbl_enabled;
+ uint32_t fw_ver;
+ uint32_t sem_timeout;
+
+ for ( k = 0; k < 1000; ++k ) {
+ uint32_t flb_status = ATL_READ_REG ( ATL_MPI_DAISY_CHAIN_STS );
+ boot_exit_code = ATL_READ_REG ( ATL_MPI_BOOT_EXIT_CODE );
+ if ( flb_status != ATL_MPI_DAISY_CHAIN_STS_ERROR_STATUS ||
+ boot_exit_code != 0 )
+ break;
+ }
+
+ if ( k == 1000 ) {
+ DBGC ( nic, "Neither RBL nor FLB firmware started\n" );
+ return -ENOTSUP;
+ }
+
+ rbl_enabled = ( boot_exit_code != 0 );
+
+ fw_ver = ATL_READ_REG ( ATL_FW_VER );
+ if ( ( ( fw_ver >> 24 ) & 0xFF ) >= 4 ) {
+ sem_timeout = ATL_READ_REG ( ATL_SEM_TIMEOUT );
+ if ( sem_timeout > ATL_SEM_MAX_TIMEOUT )
+ sem_timeout = ATL_SEM_MAX_TIMEOUT;
+
+ for ( k = 0; k < sem_timeout; ++k ) {
+ if ( ATL_READ_REG ( ATL_GLB_MCP_SEM4 ) )
+ break;
+
+ mdelay ( ATL_DELAY_1_MNS );
+ }
+ for ( k = 0; k < sem_timeout; ++k ) {
+ if ( ATL_READ_REG ( ATL_GLB_MCP_SEM5 ) )
+ break;
+
+ mdelay ( ATL_DELAY_1_MNS );
+ }
+ }
+
+
+ if ( rbl_enabled )
+ return atl_hw_reset_rbl_ ( nic );
+ else
+ return atl_hw_reset_flb_ ( nic );
+}
+
+int atl_hw_start ( struct atl_nic *nic ) {
+ ATL_WRITE_REG ( ATL_LINK_ADV_AUTONEG, ATL_LINK_ADV );
+ return 0;
+}
+
+int atl_hw_stop ( struct atl_nic *nic ) {
+ ATL_WRITE_REG ( ATL_SHUT_LINK, ATL_LINK_ADV );
+ return 0;
+}
+
+int atl_hw_get_link ( struct atl_nic *nic ) {
+ return ( ATL_READ_REG ( ATL_LINK_ST) & ATL_LINK_ADV_AUTONEG ) != 0;
+}
+
+int atl_hw_read_mem ( struct atl_nic *nic, uint32_t addr, uint32_t *buffer,
+ uint32_t size ) {
+ uint32_t i;
+
+ for ( i = 0; i < 100; ++i ) {
+ if ( ATL_READ_REG( ATL_SEM_RAM ) )
+ break;
+ mdelay ( ATL_DELAY_1_MNS );
+ }
+ if ( i == 100 ) {
+ DBGC ( nic, "Semaphore Register not set\n" );
+ return -EIO;
+ }
+
+ ATL_WRITE_REG ( addr, ATL_MBOX_CTRL3 );
+
+ for ( i = 0; i < size; ++i, addr += 4 ) {
+ uint32_t j;
+
+ ATL_WRITE_REG ( ATL_MBOX_CTRL1_START_MBOX_OPT, ATL_MBOX_CTRL1 );
+ for ( j = 0; j < 10000; ++j ) {
+ if ( ATL_READ_REG (ATL_MBOX_CTRL3 ) != addr )
+ break;
+ udelay ( ATL_DELAY_10_MNS );
+ }
+ if ( j == 10000 ) {
+ DBGC ( nic, "Reading from CTRL3 Register Failed\n" );
+ return -EIO;
+ }
+
+ buffer[i] = ATL_READ_REG ( ATL_MBOX_CTRL5 );
+ }
+
+ ATL_WRITE_REG( ATL_SEM_RAM_RESET, ATL_SEM_RAM );
+
+ return 0;
+}
+
+int atl_hw_get_mac ( struct atl_nic *nic, uint8_t *mac ) {
+ uint32_t mac_addr[2] = {0};
+ int err = 0;
+ uint32_t efuse_addr = ATL_READ_REG ( ATL_GLB_MCP_SP26 );
+
+ if ( efuse_addr != 0) {
+ uint32_t mac_efuse_addr = efuse_addr + 40 * sizeof ( uint32_t );
+ err = atl_hw_read_mem ( nic, mac_efuse_addr, mac_addr, 2 );
+ if ( err != 0 )
+ return err;
+
+ mac_addr[0] = cpu_to_be32 ( mac_addr[0] );
+ mac_addr[1] = cpu_to_be32 ( mac_addr[1] );
+
+ memcpy ( mac, ( uint8_t * )mac_addr, ATL_MAC_ADDRESS_SIZE );
+ }
+ return 0;
+}
+
+struct atl_hw_ops atl_hw = {
+ .reset = atl_hw_reset,
+ .start = atl_hw_start,
+ .stop = atl_hw_stop,
+ .get_link = atl_hw_get_link,
+ .get_mac = atl_hw_get_mac,
+};
diff --git a/src/drivers/net/marvell/atl_hw.h b/src/drivers/net/marvell/atl_hw.h
new file mode 100644
index 0000000..efc9f86
--- /dev/null
+++ b/src/drivers/net/marvell/atl_hw.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright(C) 2017-2024 Marvell
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO,THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __ATL_HW_H
+#define __ATL_HW_H
+
+FILE_LICENCE ( BSD2 );
+
+#define ATL_GLB_STD_CTRL 0x0
+#define ATL_GLB_CTRL_RST_DIS 0x4000
+#define ATL_FW_VER 0x18
+
+#define ATL_MPI_DAISY_CHAIN_STS 0x704
+#define ATL_MPI_RX_DAISY_CHAIN_DATA 0x04000000
+#define ATL_MPI_RX_DAISY_CHAIN_SOF 0x02000000
+#define FLB_LOAD_STS 0x10
+
+#define ATL_MPI_BOOT_EXIT_CODE 0x388
+
+#define ATL_SEM_TIMEOUT 0x348
+#define ATL_SEM_MAX_TIMEOUT 3000
+
+#define ATL_GLB_CTRL2 0x404
+#define ATL_GLB_MCP_SEM1 0x3A0
+#define ATL_GBL_MCP_SEM1_RELEASE 0x1
+
+#define ATL_GLB_MCP_SEM4 0x3AC
+#define ATL_GLB_MCP_SEM5 0x3B0
+#define ATL_GLB_MCP_SP26 0x364
+#define ATL_MIF_PWR_GATING_EN_CTRL 0x32A8
+
+#define ATL_GLB_NVR_PROV4 0x53C
+#define ATL_GBL_NVR_PROV4_RESET 0x10
+
+
+#define ATL_GEN_PROV9 0x520
+
+#define ATL_MAC_PHY_CTRL 0x00004000U
+#define ATL_MAC_PHY_CTRL_RST_DIS 0x20000000U
+
+#define ATL_MIF_PWR_GATING_EN_CTRL_RESET 0x0
+#define ATL_GEN_PROV9_ENABLE 0x1
+#define ATL_GLB_CTRL2_MAC_KICK_START 0x180e0
+#define ATL_GLB_CTRL2_FW_RESET 0x80e0
+#define ATL_GLB_CTRL2_MBOX_ERR_UP_RUN_STALL 0x40e1
+#define ATL_GLB_CTRL2_MBOX_ERR_UP_RUN_NORMAL 0x40e0
+#define ATL_GLB_STD_CTRL_RESET 0x8000
+#define ATL_MPI_DAISY_CHAIN_STS_ERROR_STATUS 0x06000000
+
+#define ATL_DELAY_1_MNS 1
+#define ATL_DELAY_10_MNS 10
+#define ATL_DELAY_15_MNS 15
+#define ATL_DELAY_50_MNS 50
+
+#define ATL_MAC_ADDRESS_SIZE 6
+#define POISON_SIGN 0xDEAD
+#define FW_NOT_SUPPORT 0xF1A7
+
+#endif
diff --git a/src/hci/commands/image_crypt_cmd.c b/src/hci/commands/image_crypt_cmd.c
new file mode 100644
index 0000000..26e9d79
--- /dev/null
+++ b/src/hci/commands/image_crypt_cmd.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <ipxe/image.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/imgmgmt.h>
+#include <usr/imgcrypt.h>
+
+/** @file
+ *
+ * Image encryption management commands
+ *
+ */
+
+/** "imgdecrypt" options */
+struct imgdecrypt_options {
+ /** Decrypted image name */
+ char *name;
+ /** Keep envelope after decryption */
+ int keep;
+ /** Download timeout */
+ unsigned long timeout;
+};
+
+/** "imgdecrypt" option list */
+static struct option_descriptor imgdecrypt_opts[] = {
+ OPTION_DESC ( "name", 'n', required_argument,
+ struct imgdecrypt_options, name, parse_string ),
+ OPTION_DESC ( "keep", 'k', no_argument,
+ struct imgdecrypt_options, keep, parse_flag ),
+ OPTION_DESC ( "timeout", 't', required_argument,
+ struct imgdecrypt_options, timeout, parse_timeout),
+};
+
+/** "imgdecrypt" command descriptor */
+static struct command_descriptor imgdecrypt_cmd =
+ COMMAND_DESC ( struct imgdecrypt_options, imgdecrypt_opts, 2, 2,
+ "<uri|image> <envelope uri|image>" );
+
+/**
+ * The "imgdecrypt" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int imgdecrypt_exec ( int argc, char **argv ) {
+ struct imgdecrypt_options opts;
+ const char *image_name_uri;
+ const char *envelope_name_uri;
+ struct image *image;
+ struct image *envelope;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &imgdecrypt_cmd, &opts ) ) != 0)
+ return rc;
+
+ /* Parse image name/URI string */
+ image_name_uri = argv[optind];
+
+ /* Parse envelope name/URI string */
+ envelope_name_uri = argv[ optind + 1 ];
+
+ /* Acquire the image */
+ if ( ( rc = imgacquire ( image_name_uri, opts.timeout, &image ) ) != 0 )
+ goto err_acquire_image;
+
+ /* Acquire the envelope image */
+ if ( ( rc = imgacquire ( envelope_name_uri, opts.timeout,
+ &envelope ) ) != 0 )
+ goto err_acquire_envelope;
+
+ /* Decrypt image */
+ if ( ( rc = imgdecrypt ( image, envelope, opts.name ) ) != 0 ) {
+ printf ( "Could not decrypt: %s\n", strerror ( rc ) );
+ goto err_decrypt;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_decrypt:
+ /* Discard envelope unless --keep was specified */
+ if ( ! opts.keep )
+ unregister_image ( envelope );
+ err_acquire_envelope:
+ err_acquire_image:
+ return rc;
+}
+
+/** Image encryption management commands */
+struct command image_crypt_commands[] __command = {
+ {
+ .name = "imgdecrypt",
+ .exec = imgdecrypt_exec,
+ },
+};
diff --git a/src/image/der.c b/src/image/der.c
index fa17e56..9d31c25 100644
--- a/src/image/der.c
+++ b/src/image/der.c
@@ -76,8 +76,6 @@ static int der_probe ( struct image *image ) {
struct asn1_cursor cursor;
uint8_t buf[8];
size_t extra;
- size_t total;
- int len;
int rc;
/* Sanity check: no realistic DER image can be smaller than this */
@@ -90,21 +88,16 @@ static int der_probe ( struct image *image ) {
copy_from_user ( buf, image->data, 0, sizeof ( buf ) );
extra = ( image->len - sizeof ( buf ) );
- /* Get length of ASN.1 sequence */
- len = asn1_start ( &cursor, ASN1_SEQUENCE, extra );
- if ( len < 0 ) {
- rc = len;
+ /* Check that image begins with an ASN.1 sequence object */
+ if ( ( rc = asn1_enter_partial ( &cursor, ASN1_SEQUENCE,
+ &extra ) ) != 0 ) {
DBGC ( image, "DER %s is not valid ASN.1: %s\n",
image->name, strerror ( rc ) );
return rc;
}
- /* Add length of tag and length bytes consumed by asn1_start() */
- total = ( len + ( cursor.data - ( ( void * ) buf ) ) );
- assert ( total <= image->len );
-
/* Check that image comprises a single well-formed ASN.1 object */
- if ( total != image->len ) {
+ if ( extra != ( image->len - sizeof ( buf ) ) ) {
DBGC ( image, "DER %s is not single ASN.1\n", image->name );
return -ENOEXEC;
}
diff --git a/src/include/bits/acpi.h b/src/include/bits/acpi.h
new file mode 100644
index 0000000..d984205
--- /dev/null
+++ b/src/include/bits/acpi.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_ACPI_H
+#define _BITS_ACPI_H
+
+/** @file
+ *
+ * Dummy architecture-specific ACPI API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_ACPI_H */
diff --git a/src/arch/loong64/include/gdbmach.h b/src/include/bits/gdbmach.h
index cd152ee..7e34985 100644
--- a/src/arch/loong64/include/gdbmach.h
+++ b/src/include/bits/gdbmach.h
@@ -1,12 +1,12 @@
-#ifndef GDBMACH_H
-#define GDBMACH_H
+#ifndef _BITS_GDBMACH_H
+#define _BITS_GDBMACH_H
/** @file
*
- * GDB architecture specifics
+ * Dummy GDB architecture specifics
*
- * This file declares functions for manipulating the machine state and
- * debugging context.
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
*
*/
@@ -42,4 +42,4 @@ extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len,
int enable );
extern void gdbmach_init ( void );
-#endif /* GDBMACH_H */
+#endif /* _BITS_GDBMACH_H */
diff --git a/src/include/bits/hyperv.h b/src/include/bits/hyperv.h
new file mode 100644
index 0000000..fd7ceee
--- /dev/null
+++ b/src/include/bits/hyperv.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_HYPERV_H
+#define _BITS_HYPERV_H
+
+/** @file
+ *
+ * Dummy architecture-specific Hyper-V interface
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_HYPERV_H */
diff --git a/src/include/bits/iomap.h b/src/include/bits/iomap.h
new file mode 100644
index 0000000..b3d8d0c
--- /dev/null
+++ b/src/include/bits/iomap.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_IOMAP_H
+#define _BITS_IOMAP_H
+
+/** @file
+ *
+ * Dummy architecture-specific I/O mapping API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_IOMAP_H */
diff --git a/src/include/bits/mp.h b/src/include/bits/mp.h
new file mode 100644
index 0000000..d7d2cdc
--- /dev/null
+++ b/src/include/bits/mp.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_MP_H
+#define _BITS_MP_H
+
+/** @file
+ *
+ * Dummy architecture-specific multiprocessor API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_MP_H */
diff --git a/src/include/bits/nap.h b/src/include/bits/nap.h
new file mode 100644
index 0000000..7b01f94
--- /dev/null
+++ b/src/include/bits/nap.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_NAP_H
+#define _BITS_NAP_H
+
+/** @file
+ *
+ * Dummy architecture-specific CPU sleeping API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_NAP_H */
diff --git a/src/include/bits/pci_io.h b/src/include/bits/pci_io.h
new file mode 100644
index 0000000..711449f
--- /dev/null
+++ b/src/include/bits/pci_io.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_PCI_IO_H
+#define _BITS_PCI_IO_H
+
+/** @file
+ *
+ * Dummy architecture-specific PCI I/O API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_PCI_IO_H */
diff --git a/src/include/bits/reboot.h b/src/include/bits/reboot.h
new file mode 100644
index 0000000..023647f
--- /dev/null
+++ b/src/include/bits/reboot.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_REBOOT_H
+#define _BITS_REBOOT_H
+
+/** @file
+ *
+ * Dummy architecture-specific reboot API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_REBOOT_H */
diff --git a/src/include/bits/sanboot.h b/src/include/bits/sanboot.h
new file mode 100644
index 0000000..addbb5b
--- /dev/null
+++ b/src/include/bits/sanboot.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_SANBOOT_H
+#define _BITS_SANBOOT_H
+
+/** @file
+ *
+ * Dummy architecture-specific sanboot API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_SANBOOT_H */
diff --git a/src/include/bits/smbios.h b/src/include/bits/smbios.h
new file mode 100644
index 0000000..3e06aad
--- /dev/null
+++ b/src/include/bits/smbios.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_SMBIOS_H
+#define _BITS_SMBIOS_H
+
+/** @file
+ *
+ * Dummy architecture-specific SMBIOS API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_SMBIOS_H */
diff --git a/src/include/bits/tcpip.h b/src/include/bits/tcpip.h
new file mode 100644
index 0000000..9cb54d4
--- /dev/null
+++ b/src/include/bits/tcpip.h
@@ -0,0 +1,32 @@
+#ifndef _BITS_TCPIP_H
+#define _BITS_TCPIP_H
+
+/** @file
+ *
+ * Generic architecture-specific transport-network layer interface
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdint.h>
+
+/**
+ * Calculate continued TCP/IP checkum
+ *
+ * @v partial Checksum of already-summed data, in network byte order
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret cksum Updated checksum, in network byte order
+ */
+static inline __attribute__ (( always_inline )) uint16_t
+tcpip_continue_chksum ( uint16_t partial, const void *data, size_t len ) {
+
+ /* Not yet optimised */
+ return generic_tcpip_continue_chksum ( partial, data, len );
+}
+
+#endif /* _BITS_TCPIP_H */
diff --git a/src/include/bits/time.h b/src/include/bits/time.h
new file mode 100644
index 0000000..aec9c2f
--- /dev/null
+++ b/src/include/bits/time.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_TIME_H
+#define _BITS_TIME_H
+
+/** @file
+ *
+ * Dummy architecture-specific time API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_TIME_H */
diff --git a/src/include/bits/uaccess.h b/src/include/bits/uaccess.h
new file mode 100644
index 0000000..09f5f46
--- /dev/null
+++ b/src/include/bits/uaccess.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_UACCESS_H
+#define _BITS_UACCESS_H
+
+/** @file
+ *
+ * Dummy architecture-specific user access API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_UACCESS_H */
diff --git a/src/include/bits/uart.h b/src/include/bits/uart.h
new file mode 100644
index 0000000..e132d5c
--- /dev/null
+++ b/src/include/bits/uart.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_UART_H
+#define _BITS_UART_H
+
+/** @file
+ *
+ * Dummy architecture-specific UART
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_UART_H */
diff --git a/src/include/bits/umalloc.h b/src/include/bits/umalloc.h
new file mode 100644
index 0000000..4927f0d
--- /dev/null
+++ b/src/include/bits/umalloc.h
@@ -0,0 +1,15 @@
+#ifndef _BITS_UMALLOC_H
+#define _BITS_UMALLOC_H
+
+/** @file
+ *
+ * Dummy architecture-specific user memory allocation API implementations
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#endif /* _BITS_UMALLOC_H */
diff --git a/src/arch/loong64/include/bits/xen.h b/src/include/bits/xen.h
index 2a3d774..7d0036b 100644
--- a/src/arch/loong64/include/bits/xen.h
+++ b/src/include/bits/xen.h
@@ -3,7 +3,10 @@
/** @file
*
- * Xen interface
+ * Dummy architecture-specific Xen interface
+ *
+ * This file is included only if the architecture does not provide its
+ * own version of this file.
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h
index ac7ea56..752b423 100644
--- a/src/include/ipxe/asn1.h
+++ b/src/include/ipxe/asn1.h
@@ -192,6 +192,48 @@ struct asn1_builder_header {
ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 101 ), \
ASN1_OID_SINGLE ( 110 )
+/** ASN.1 OID for id-aes128-cbc (2.16.840.1.101.3.4.1.2) */
+#define ASN1_OID_AES128_CBC \
+ ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 101 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 2 )
+
+/** ASN.1 OID for id-aes128-gcm (2.16.840.1.101.3.4.1.6) */
+#define ASN1_OID_AES128_GCM \
+ ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 101 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 6 )
+
+/** ASN.1 OID for id-aes192-cbc (2.16.840.1.101.3.4.1.22) */
+#define ASN1_OID_AES192_CBC \
+ ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 101 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 22 )
+
+/** ASN.1 OID for id-aes192-gcm (2.16.840.1.101.3.4.1.26) */
+#define ASN1_OID_AES192_GCM \
+ ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 101 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 26 )
+
+/** ASN.1 OID for id-aes256-cbc (2.16.840.1.101.3.4.1.42) */
+#define ASN1_OID_AES256_CBC \
+ ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 101 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 42 )
+
+/** ASN.1 OID for id-aes256-gcm (2.16.840.1.101.3.4.1.46) */
+#define ASN1_OID_AES256_GCM \
+ ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 101 ), \
+ ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 46 )
+
/** ASN.1 OID for id-sha256 (2.16.840.1.101.3.4.2.1) */
#define ASN1_OID_SHA256 \
ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \
@@ -261,12 +303,25 @@ struct asn1_builder_header {
ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \
ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 3 )
-/** ASN.1 OID for pkcs-signedData (1.2.840.113549.1.7.2) */
+/** ASN.1 OID for id-signedData (1.2.840.113549.1.7.2) */
#define ASN1_OID_SIGNEDDATA \
ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \
ASN1_OID_SINGLE ( 7 ), ASN1_OID_SINGLE ( 2 )
+/** ASN.1 OID for id-envelopedData (1.2.840.113549.1.7.3) */
+#define ASN1_OID_ENVELOPEDDATA \
+ ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \
+ ASN1_OID_SINGLE ( 7 ), ASN1_OID_SINGLE ( 3 )
+
+/** ASN.1 OID for id-authEnvelopedData (1.2.840.113549.1.9.16.1.23) */
+#define ASN1_OID_AUTHENVELOPEDDATA \
+ ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
+ ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \
+ ASN1_OID_SINGLE ( 9 ), ASN1_OID_SINGLE ( 16 ), \
+ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 23 )
+
/** ASN.1 OID for id-pe-authorityInfoAccess (1.3.6.1.5.5.7.1.1) */
#define ASN1_OID_AUTHORITYINFOACCESS \
ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \
@@ -317,8 +372,19 @@ struct asn1_algorithm {
struct pubkey_algorithm *pubkey;
/** Digest algorithm (if applicable) */
struct digest_algorithm *digest;
+ /** Cipher algorithm (if applicable) */
+ struct cipher_algorithm *cipher;
/** Elliptic curve (if applicable) */
struct elliptic_curve *curve;
+ /**
+ * Parse algorithm parameters (optional)
+ *
+ * @v algorithm Algorithm
+ * @v param Parameters to parse (and potentially modify)
+ * @ret rc Return status code
+ */
+ int ( * parse ) ( struct asn1_algorithm *algorithm,
+ struct asn1_cursor *params );
};
/** ASN.1 OID-identified algorithms */
@@ -404,8 +470,8 @@ asn1_built ( struct asn1_builder *builder ) {
return &u->cursor;
}
-extern int asn1_start ( struct asn1_cursor *cursor, unsigned int type,
- size_t extra );
+extern int asn1_enter_partial ( struct asn1_cursor *cursor, unsigned int type,
+ size_t *extra );
extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
unsigned int type );
@@ -423,15 +489,23 @@ extern int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
extern int asn1_compare ( const struct asn1_cursor *cursor1,
const struct asn1_cursor *cursor2 );
extern int asn1_algorithm ( const struct asn1_cursor *cursor,
- struct asn1_algorithm **algorithm );
+ struct asn1_algorithm **algorithm,
+ struct asn1_cursor *params );
extern int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm );
extern int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm );
+extern int asn1_cipher_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm **algorithm,
+ struct asn1_cursor *params );
extern int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm );
extern int asn1_check_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm *expected );
+extern int asn1_parse_cbc ( struct asn1_algorithm *algorithm,
+ struct asn1_cursor *params );
+extern int asn1_parse_gcm ( struct asn1_algorithm *algorithm,
+ struct asn1_cursor *params );
extern int asn1_generalized_time ( const struct asn1_cursor *cursor,
time_t *time );
extern int asn1_grow ( struct asn1_builder *builder, size_t extra );
diff --git a/src/include/ipxe/certstore.h b/src/include/ipxe/certstore.h
index ce96666..e276d67 100644
--- a/src/include/ipxe/certstore.h
+++ b/src/include/ipxe/certstore.h
@@ -9,14 +9,10 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-#include <ipxe/asn1.h>
#include <ipxe/x509.h>
-#include <ipxe/privkey.h>
extern struct x509_chain certstore;
-extern struct x509_certificate * certstore_find ( struct asn1_cursor *raw );
-extern struct x509_certificate * certstore_find_key ( struct private_key *key );
extern void certstore_add ( struct x509_certificate *cert );
extern void certstore_del ( struct x509_certificate *cert );
diff --git a/src/include/ipxe/cms.h b/src/include/ipxe/cms.h
index 7adf724..6d4a78d 100644
--- a/src/include/ipxe/cms.h
+++ b/src/include/ipxe/cms.h
@@ -16,61 +16,116 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/refcnt.h>
#include <ipxe/uaccess.h>
-/** CMS signer information */
-struct cms_signer_info {
- /** List of signer information blocks */
- struct list_head list;
+struct image;
+struct cms_message;
+
+/** A CMS message type */
+struct cms_type {
+ /** Name */
+ const char *name;
+ /** Object identifier */
+ struct asn1_cursor oid;
+ /** Parse content
+ *
+ * @v cms CMS message
+ * @v raw ASN.1 cursor
+ * @ret rc Return status code
+ */
+ int ( * parse ) ( struct cms_message *cms,
+ const struct asn1_cursor *raw );
+};
+/** CMS participant information */
+struct cms_participant {
+ /** List of participant information blocks */
+ struct list_head list;
/** Certificate chain */
struct x509_chain *chain;
- /** Digest algorithm */
+ /** Digest algorithm (for signature messages) */
struct digest_algorithm *digest;
/** Public-key algorithm */
struct pubkey_algorithm *pubkey;
- /** Signature */
- void *signature;
- /** Length of signature */
- size_t signature_len;
+ /** Signature or key value */
+ struct asn1_cursor value;
};
-/** A CMS signature */
-struct cms_signature {
+/** A CMS message */
+struct cms_message {
/** Reference count */
struct refcnt refcnt;
- /** List of all certificates */
+ /** Raw ASN.1 data */
+ struct asn1_cursor *raw;
+ /** Message type */
+ struct cms_type *type;
+
+ /** List of all certificates (for signature messages) */
struct x509_chain *certificates;
- /** List of signer information blocks */
- struct list_head info;
+ /** List of participant information blocks */
+ struct list_head participants;
+
+ /** Cipher algorithm */
+ struct cipher_algorithm *cipher;
+ /** Cipher initialization vector */
+ struct asn1_cursor iv;
+ /** Cipher authentication tag */
+ struct asn1_cursor mac;
};
/**
- * Get reference to CMS signature
+ * Get reference to CMS message
*
- * @v sig CMS signature
- * @ret sig CMS signature
+ * @v cms CMS message
+ * @ret cms CMS message
*/
-static inline __attribute__ (( always_inline )) struct cms_signature *
-cms_get ( struct cms_signature *sig ) {
- ref_get ( &sig->refcnt );
- return sig;
+static inline __attribute__ (( always_inline )) struct cms_message *
+cms_get ( struct cms_message *cms ) {
+ ref_get ( &cms->refcnt );
+ return cms;
}
/**
- * Drop reference to CMS signature
+ * Drop reference to CMS message
*
- * @v sig CMS signature
+ * @v cms CMS message
*/
static inline __attribute__ (( always_inline )) void
-cms_put ( struct cms_signature *sig ) {
- ref_put ( &sig->refcnt );
+cms_put ( struct cms_message *cms ) {
+ ref_put ( &cms->refcnt );
+}
+
+/**
+ * Check if CMS message is a signature message
+ *
+ * @v cms CMS message
+ * @ret is_signature Message is a signature message
+ */
+static inline __attribute__ (( always_inline )) int
+cms_is_signature ( struct cms_message *cms ) {
+
+ /* CMS signatures include an optional CertificateSet */
+ return ( cms->certificates != NULL );
+}
+
+/**
+ * Check if CMS message is an encrypted message
+ *
+ * @v cms CMS message
+ * @ret is_encrypted Message is an encrypted message
+ */
+static inline __attribute__ (( always_inline )) int
+cms_is_encrypted ( struct cms_message *cms ) {
+
+ /* CMS encrypted messages have a cipher algorithm */
+ return ( cms->cipher != NULL );
}
-extern int cms_signature ( const void *data, size_t len,
- struct cms_signature **sig );
-extern int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
+extern int cms_message ( struct image *image, struct cms_message **cms );
+extern int cms_verify ( struct cms_message *cms, struct image *image,
const char *name, time_t time, struct x509_chain *store,
struct x509_root *root );
+extern int cms_decrypt ( struct cms_message *cms, struct image *image,
+ const char *name, struct private_key *private_key );
#endif /* _IPXE_CMS_H */
diff --git a/src/include/ipxe/crypto.h b/src/include/ipxe/crypto.h
index a6f4376..dcc73f3 100644
--- a/src/include/ipxe/crypto.h
+++ b/src/include/ipxe/crypto.h
@@ -12,6 +12,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stddef.h>
#include <assert.h>
+#include <ipxe/asn1.h>
/** A message digest algorithm */
struct digest_algorithm {
@@ -120,79 +121,63 @@ struct cipher_algorithm {
struct pubkey_algorithm {
/** Algorithm name */
const char *name;
- /** Context size */
- size_t ctxsize;
- /** Initialise algorithm
- *
- * @v ctx Context
- * @v key Key
- * @v key_len Length of key
- * @ret rc Return status code
- */
- int ( * init ) ( void *ctx, const void *key, size_t key_len );
/** Calculate maximum output length
*
- * @v ctx Context
+ * @v key Key
* @ret max_len Maximum output length
*/
- size_t ( * max_len ) ( void *ctx );
+ size_t ( * max_len ) ( const struct asn1_cursor *key );
/** Encrypt
*
- * @v ctx Context
+ * @v key Key
* @v plaintext Plaintext
* @v plaintext_len Length of plaintext
* @v ciphertext Ciphertext
* @ret ciphertext_len Length of ciphertext, or negative error
*/
- int ( * encrypt ) ( void *ctx, const void *data, size_t len,
- void *out );
+ int ( * encrypt ) ( const struct asn1_cursor *key, const void *data,
+ size_t len, void *out );
/** Decrypt
*
- * @v ctx Context
+ * @v key Key
* @v ciphertext Ciphertext
* @v ciphertext_len Ciphertext length
* @v plaintext Plaintext
* @ret plaintext_len Plaintext length, or negative error
*/
- int ( * decrypt ) ( void *ctx, const void *data, size_t len,
- void *out );
+ int ( * decrypt ) ( const struct asn1_cursor *key, const void *data,
+ size_t len, void *out );
/** Sign digest value
*
- * @v ctx Context
+ * @v key Key
* @v digest Digest algorithm
* @v value Digest value
* @v signature Signature
* @ret signature_len Signature length, or negative error
*/
- int ( * sign ) ( void *ctx, struct digest_algorithm *digest,
- const void *value, void *signature );
+ int ( * sign ) ( const struct asn1_cursor *key,
+ struct digest_algorithm *digest, const void *value,
+ void *signature );
/** Verify signed digest value
*
- * @v ctx Context
+ * @v key Key
* @v digest Digest algorithm
* @v value Digest value
* @v signature Signature
* @v signature_len Signature length
* @ret rc Return status code
*/
- int ( * verify ) ( void *ctx, struct digest_algorithm *digest,
- const void *value, const void *signature,
- size_t signature_len );
- /** Finalise algorithm
- *
- * @v ctx Context
- */
- void ( * final ) ( void *ctx );
+ int ( * verify ) ( const struct asn1_cursor *key,
+ struct digest_algorithm *digest, const void *value,
+ const void *signature, size_t signature_len );
/** Check that public key matches private key
*
* @v private_key Private key
- * @v private_key_len Private key length
* @v public_key Public key
- * @v public_key_len Public key length
* @ret rc Return status code
*/
- int ( * match ) ( const void *private_key, size_t private_key_len,
- const void *public_key, size_t public_key_len );
+ int ( * match ) ( const struct asn1_cursor *private_key,
+ const struct asn1_cursor *public_key );
};
/** An elliptic curve */
@@ -280,54 +265,43 @@ is_auth_cipher ( struct cipher_algorithm *cipher ) {
return cipher->authsize;
}
-static inline __attribute__ (( always_inline )) int
-pubkey_init ( struct pubkey_algorithm *pubkey, void *ctx,
- const void *key, size_t key_len ) {
- return pubkey->init ( ctx, key, key_len );
-}
-
static inline __attribute__ (( always_inline )) size_t
-pubkey_max_len ( struct pubkey_algorithm *pubkey, void *ctx ) {
- return pubkey->max_len ( ctx );
+pubkey_max_len ( struct pubkey_algorithm *pubkey,
+ const struct asn1_cursor *key ) {
+ return pubkey->max_len ( key );
}
static inline __attribute__ (( always_inline )) int
-pubkey_encrypt ( struct pubkey_algorithm *pubkey, void *ctx,
+pubkey_encrypt ( struct pubkey_algorithm *pubkey, const struct asn1_cursor *key,
const void *data, size_t len, void *out ) {
- return pubkey->encrypt ( ctx, data, len, out );
+ return pubkey->encrypt ( key, data, len, out );
}
static inline __attribute__ (( always_inline )) int
-pubkey_decrypt ( struct pubkey_algorithm *pubkey, void *ctx,
+pubkey_decrypt ( struct pubkey_algorithm *pubkey, const struct asn1_cursor *key,
const void *data, size_t len, void *out ) {
- return pubkey->decrypt ( ctx, data, len, out );
+ return pubkey->decrypt ( key, data, len, out );
}
static inline __attribute__ (( always_inline )) int
-pubkey_sign ( struct pubkey_algorithm *pubkey, void *ctx,
+pubkey_sign ( struct pubkey_algorithm *pubkey, const struct asn1_cursor *key,
struct digest_algorithm *digest, const void *value,
void *signature ) {
- return pubkey->sign ( ctx, digest, value, signature );
+ return pubkey->sign ( key, digest, value, signature );
}
static inline __attribute__ (( always_inline )) int
-pubkey_verify ( struct pubkey_algorithm *pubkey, void *ctx,
+pubkey_verify ( struct pubkey_algorithm *pubkey, const struct asn1_cursor *key,
struct digest_algorithm *digest, const void *value,
const void *signature, size_t signature_len ) {
- return pubkey->verify ( ctx, digest, value, signature, signature_len );
-}
-
-static inline __attribute__ (( always_inline )) void
-pubkey_final ( struct pubkey_algorithm *pubkey, void *ctx ) {
- pubkey->final ( ctx );
+ return pubkey->verify ( key, digest, value, signature, signature_len );
}
static inline __attribute__ (( always_inline )) int
pubkey_match ( struct pubkey_algorithm *pubkey,
- const void *private_key, size_t private_key_len,
- const void *public_key, size_t public_key_len ) {
- return pubkey->match ( private_key, private_key_len, public_key,
- public_key_len );
+ const struct asn1_cursor *private_key,
+ const struct asn1_cursor *public_key ) {
+ return pubkey->match ( private_key, public_key );
}
static inline __attribute__ (( always_inline )) int
@@ -348,15 +322,18 @@ extern void cipher_null_decrypt ( void *ctx, const void *src, void *dst,
size_t len );
extern void cipher_null_auth ( void *ctx, void *auth );
-extern int pubkey_null_init ( void *ctx, const void *key, size_t key_len );
-extern size_t pubkey_null_max_len ( void *ctx );
-extern int pubkey_null_encrypt ( void *ctx, const void *plaintext,
- size_t plaintext_len, void *ciphertext );
-extern int pubkey_null_decrypt ( void *ctx, const void *ciphertext,
- size_t ciphertext_len, void *plaintext );
-extern int pubkey_null_sign ( void *ctx, struct digest_algorithm *digest,
+extern size_t pubkey_null_max_len ( const struct asn1_cursor *key );
+extern int pubkey_null_encrypt ( const struct asn1_cursor *key,
+ const void *plaintext, size_t plaintext_len,
+ void *ciphertext );
+extern int pubkey_null_decrypt ( const struct asn1_cursor *key,
+ const void *ciphertext, size_t ciphertext_len,
+ void *plaintext );
+extern int pubkey_null_sign ( const struct asn1_cursor *key,
+ struct digest_algorithm *digest,
const void *value, void *signature );
-extern int pubkey_null_verify ( void *ctx, struct digest_algorithm *digest,
+extern int pubkey_null_verify ( const struct asn1_cursor *key,
+ struct digest_algorithm *digest,
const void *value, const void *signature ,
size_t signature_len );
diff --git a/src/include/ipxe/ecam.h b/src/include/ipxe/ecam.h
index ff08aee..f656083 100644
--- a/src/include/ipxe/ecam.h
+++ b/src/include/ipxe/ecam.h
@@ -54,6 +54,16 @@ struct ecam_mapping {
int rc;
};
+/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( ecam, pci_can_probe ) ( void ) {
+ return 1;
+}
+
extern struct pci_api ecam_api;
#endif /* _IPXE_ECAM_H */
diff --git a/src/include/ipxe/efi/efi_pci_api.h b/src/include/ipxe/efi/efi_pci_api.h
index cf5e1d0..9aca02f 100644
--- a/src/include/ipxe/efi/efi_pci_api.h
+++ b/src/include/ipxe/efi/efi_pci_api.h
@@ -33,17 +33,13 @@ extern int efipci_write ( struct pci_device *pci, unsigned long location,
unsigned long value );
/**
- * Find next PCI bus:dev.fn address range in system
+ * Check if PCI bus probing is allowed
*
- * @v busdevfn Starting PCI bus:dev.fn address
- * @v range PCI bus:dev.fn address range to fill in
+ * @ret ok Bus probing is allowed
*/
-static inline __always_inline void
-PCIAPI_INLINE ( efi, pci_discover ) ( uint32_t busdevfn __unused,
- struct pci_range *range ) {
-
- /* EFI does not want us to scan the PCI bus ourselves */
- range->count = 0;
+static inline __always_inline int
+PCIAPI_INLINE ( efi, pci_can_probe ) ( void ) {
+ return 0;
}
/**
diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h
index 7615075..42bc177 100644
--- a/src/include/ipxe/errfile.h
+++ b/src/include/ipxe/errfile.h
@@ -225,6 +225,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_pcibridge ( ERRFILE_DRIVER | 0x00d40000 )
#define ERRFILE_mnpnet ( ERRFILE_DRIVER | 0x00d50000 )
#define ERRFILE_gve ( ERRFILE_DRIVER | 0x00d60000 )
+#define ERRFILE_aqc1xx ( ERRFILE_DRIVER | 0x00d70000 )
+#define ERRFILE_atl_hw ( ERRFILE_DRIVER | 0x00d80000 )
+#define ERRFILE_atl2_hw ( ERRFILE_DRIVER | 0x00d90000 )
#define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 )
#define ERRFILE_arp ( ERRFILE_NET | 0x00010000 )
diff --git a/src/include/ipxe/gdbstub.h b/src/include/ipxe/gdbstub.h
index 13ca33d..2240cca 100644
--- a/src/include/ipxe/gdbstub.h
+++ b/src/include/ipxe/gdbstub.h
@@ -11,7 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/tables.h>
-#include <gdbmach.h>
+#include <bits/gdbmach.h>
/**
* A transport mechanism for the GDB protocol
diff --git a/src/include/ipxe/image.h b/src/include/ipxe/image.h
index bfbf236..ca383dc 100644
--- a/src/include/ipxe/image.h
+++ b/src/include/ipxe/image.h
@@ -188,6 +188,7 @@ static inline struct image * first_image ( void ) {
extern struct image * alloc_image ( struct uri *uri );
extern int image_set_uri ( struct image *image, struct uri *uri );
extern int image_set_name ( struct image *image, const char *name );
+extern char * image_strip_suffix ( struct image *image );
extern int image_set_cmdline ( struct image *image, const char *cmdline );
extern int image_set_len ( struct image *image, size_t len );
extern int image_set_data ( struct image *image, userptr_t data, size_t len );
diff --git a/src/include/ipxe/linux/linux_pci.h b/src/include/ipxe/linux/linux_pci.h
index ec6ff8b..2b19e13 100644
--- a/src/include/ipxe/linux/linux_pci.h
+++ b/src/include/ipxe/linux/linux_pci.h
@@ -23,6 +23,16 @@ extern int linux_pci_write ( struct pci_device *pci, unsigned long where,
unsigned long value, size_t len );
/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok Bus probing is allowed
+ */
+static inline __always_inline int
+PCIAPI_INLINE ( linux, pci_can_probe ) ( void ) {
+ return 1;
+}
+
+/**
* Find next PCI bus:dev.fn address range in system
*
* @v busdevfn Starting PCI bus:dev.fn address
diff --git a/src/include/ipxe/pci_io.h b/src/include/ipxe/pci_io.h
index 4c035b1..322fdbb 100644
--- a/src/include/ipxe/pci_io.h
+++ b/src/include/ipxe/pci_io.h
@@ -67,6 +67,13 @@ struct pci_range {
#include <bits/pci_io.h>
/**
+ * Check if PCI bus probing is allowed
+ *
+ * @ret ok Bus probing is allowed
+ */
+int pci_can_probe ( void );
+
+/**
* Find next PCI bus:dev.fn address range in system
*
* @v busdevfn Starting PCI bus:dev.fn address
diff --git a/src/include/ipxe/rsa.h b/src/include/ipxe/rsa.h
index a1b5e0c..e36a75e 100644
--- a/src/include/ipxe/rsa.h
+++ b/src/include/ipxe/rsa.h
@@ -55,31 +55,6 @@ struct rsa_digestinfo_prefix {
/** Declare an RSA digestInfo prefix */
#define __rsa_digestinfo_prefix __table_entry ( RSA_DIGESTINFO_PREFIXES, 01 )
-/** An RSA context */
-struct rsa_context {
- /** Allocated memory */
- void *dynamic;
- /** Modulus */
- bigint_element_t *modulus0;
- /** Modulus size */
- unsigned int size;
- /** Modulus length */
- size_t max_len;
- /** Exponent */
- bigint_element_t *exponent0;
- /** Exponent size */
- unsigned int exponent_size;
- /** Input buffer */
- bigint_element_t *input0;
- /** Output buffer */
- bigint_element_t *output0;
- /** Temporary working space for modular exponentiation */
- void *tmp;
-};
-
-/** RSA context size */
-#define RSA_CTX_SIZE sizeof ( struct rsa_context )
-
extern struct pubkey_algorithm rsa_algorithm;
#endif /* _IPXE_RSA_H */
diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h
index cf32778..08d5868 100644
--- a/src/include/ipxe/tls.h
+++ b/src/include/ipxe/tls.h
@@ -240,8 +240,6 @@ struct tls_cipherspec {
struct tls_cipher_suite *suite;
/** Dynamically-allocated storage */
void *dynamic;
- /** Public key encryption context */
- void *pubkey_ctx;
/** Bulk encryption cipher context */
void *cipher_ctx;
/** MAC secret */
@@ -250,6 +248,14 @@ struct tls_cipherspec {
void *fixed_iv;
};
+/** A TLS cipher specification pair */
+struct tls_cipherspec_pair {
+ /** Current cipher specification */
+ struct tls_cipherspec active;
+ /** Next cipher specification */
+ struct tls_cipherspec pending;
+};
+
/** A TLS signature and hash algorithm identifier */
struct tls_signature_hash_id {
/** Hash algorithm */
@@ -340,6 +346,70 @@ struct tls_session {
struct list_head conn;
};
+/** TLS transmit state */
+struct tls_tx {
+ /** Cipher specifications */
+ struct tls_cipherspec_pair cipherspec;
+ /** Sequence number */
+ uint64_t seq;
+ /** Pending transmissions */
+ unsigned int pending;
+ /** Transmit process */
+ struct process process;
+};
+
+/** TLS receive state */
+struct tls_rx {
+ /** Cipher specifications */
+ struct tls_cipherspec_pair cipherspec;
+ /** Sequence number */
+ uint64_t seq;
+ /** State machine current state */
+ enum tls_rx_state state;
+ /** Current received record header */
+ struct tls_header header;
+ /** Current received record header (static I/O buffer) */
+ struct io_buffer iobuf;
+ /** List of received data buffers */
+ struct list_head data;
+ /** Received handshake fragment */
+ struct io_buffer *handshake;
+};
+
+/** TLS client state */
+struct tls_client {
+ /** Random bytes */
+ struct tls_client_random random;
+ /** Private key (if used) */
+ struct private_key *key;
+ /** Certificate chain (if used) */
+ struct x509_chain *chain;
+ /** Security negotiation pending operation */
+ struct pending_operation negotiation;
+};
+
+/** TLS server state */
+struct tls_server {
+ /** Random bytes */
+ uint8_t random[32];
+ /** Server Key Exchange record (if any) */
+ void *exchange;
+ /** Server Key Exchange record length */
+ size_t exchange_len;
+ /** Root of trust */
+ struct x509_root *root;
+ /** Certificate chain */
+ struct x509_chain *chain;
+ /** Public key (within server certificate) */
+ struct asn1_cursor key;
+ /** Certificate validator */
+ struct interface validator;
+ /** Certificate validation pending operation */
+ struct pending_operation validation;
+ /** Security negotiation pending operation */
+ struct pending_operation negotiation;
+};
+
/** A TLS connection */
struct tls_connection {
/** Reference counter */
@@ -365,70 +435,25 @@ struct tls_connection {
/** Protocol version */
uint16_t version;
- /** Current TX cipher specification */
- struct tls_cipherspec tx_cipherspec;
- /** Next TX cipher specification */
- struct tls_cipherspec tx_cipherspec_pending;
- /** Current RX cipher specification */
- struct tls_cipherspec rx_cipherspec;
- /** Next RX cipher specification */
- struct tls_cipherspec rx_cipherspec_pending;
/** Master secret */
uint8_t master_secret[48];
- /** Server random bytes */
- uint8_t server_random[32];
- /** Client random bytes */
- struct tls_client_random client_random;
- /** Server Key Exchange record (if any) */
- void *server_key;
- /** Server Key Exchange record length */
- size_t server_key_len;
/** Digest algorithm used for handshake verification */
struct digest_algorithm *handshake_digest;
/** Digest algorithm context used for handshake verification */
uint8_t *handshake_ctx;
- /** Private key */
- struct private_key *key;
- /** Client certificate chain (if used) */
- struct x509_chain *certs;
/** Secure renegotiation flag */
int secure_renegotiation;
/** Verification data */
struct tls_verify_data verify;
- /** Root of trust */
- struct x509_root *root;
- /** Server certificate chain */
- struct x509_chain *chain;
- /** Certificate validator */
- struct interface validator;
-
- /** Client security negotiation pending operation */
- struct pending_operation client_negotiation;
- /** Server security negotiation pending operation */
- struct pending_operation server_negotiation;
- /** Certificate validation pending operation */
- struct pending_operation validation;
-
- /** TX sequence number */
- uint64_t tx_seq;
- /** TX pending transmissions */
- unsigned int tx_pending;
- /** TX process */
- struct process process;
-
- /** RX sequence number */
- uint64_t rx_seq;
- /** RX state */
- enum tls_rx_state rx_state;
- /** Current received record header */
- struct tls_header rx_header;
- /** Current received record header (static I/O buffer) */
- struct io_buffer rx_header_iobuf;
- /** List of received data buffers */
- struct list_head rx_data;
- /** Received handshake fragment */
- struct io_buffer *rx_handshake;
+ /** Transmit state */
+ struct tls_tx tx;
+ /** Receive state */
+ struct tls_rx rx;
+ /** Client state */
+ struct tls_client client;
+ /** Server state */
+ struct tls_server server;
};
/** RX I/O buffer size
diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h
index 87323ce..e71cee8 100644
--- a/src/include/ipxe/x509.h
+++ b/src/include/ipxe/x509.h
@@ -17,6 +17,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/list.h>
struct image;
+struct private_key;
/** An X.509 serial number */
struct x509_serial {
@@ -201,6 +202,13 @@ struct x509_chain {
struct refcnt refcnt;
/** List of links */
struct list_head links;
+ /** Mark certificate as found
+ *
+ * @v store Certificate store
+ * @v cert X.509 certificate
+ */
+ void ( * found ) ( struct x509_chain *store,
+ struct x509_certificate *cert );
};
/** An X.509 certificate */
@@ -424,8 +432,19 @@ extern int x509_append ( struct x509_chain *chain,
extern int x509_append_raw ( struct x509_chain *chain, const void *data,
size_t len );
extern void x509_truncate ( struct x509_chain *chain, struct x509_link *link );
+extern struct x509_certificate * x509_find ( struct x509_chain *store,
+ const struct asn1_cursor *raw );
+extern struct x509_certificate *
+x509_find_subject ( struct x509_chain *store,
+ const struct asn1_cursor *subject );
+extern struct x509_certificate *
+x509_find_issuer_serial ( struct x509_chain *store,
+ const struct asn1_cursor *issuer,
+ const struct asn1_cursor *serial );
+extern struct x509_certificate * x509_find_key ( struct x509_chain *store,
+ struct private_key *key );
extern int x509_auto_append ( struct x509_chain *chain,
- struct x509_chain *certs );
+ struct x509_chain *store );
extern int x509_validate_chain ( struct x509_chain *chain, time_t time,
struct x509_chain *store,
struct x509_root *root );
diff --git a/src/include/usr/imgcrypt.h b/src/include/usr/imgcrypt.h
new file mode 100644
index 0000000..c9408c7
--- /dev/null
+++ b/src/include/usr/imgcrypt.h
@@ -0,0 +1,17 @@
+#ifndef _USR_IMGCRYPT_H
+#define _USR_IMGCRYPT_H
+
+/** @file
+ *
+ * Image encryption management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/image.h>
+
+extern int imgdecrypt ( struct image *image, struct image *envelope,
+ const char *name );
+
+#endif /* _USR_IMGCRYPT_H */
diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c
index e2eeeb3..8d4e085 100644
--- a/src/interface/efi/efi_pci.c
+++ b/src/interface/efi/efi_pci.c
@@ -63,91 +63,139 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
/**
- * Check for a matching PCI root bridge I/O protocol
+ * Find closest bus:dev.fn address range within a root bridge
*
- * @v pci PCI device
+ * @v pci Starting PCI device
* @v handle EFI PCI root bridge handle
- * @v root EFI PCI root bridge I/O protocol
+ * @v range PCI bus:dev.fn address range to fill in
* @ret rc Return status code
*/
-static int efipci_root_match ( struct pci_device *pci, EFI_HANDLE handle,
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root ) {
+static int efipci_discover_one ( struct pci_device *pci, EFI_HANDLE handle,
+ struct pci_range *range ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ union {
+ void *interface;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root;
+ } root;
union {
union acpi_resource *res;
void *raw;
- } u;
- unsigned int segment = PCI_SEG ( pci->busdevfn );
- unsigned int bus = PCI_BUS ( pci->busdevfn );
- unsigned int start;
- unsigned int end;
+ } acpi;
+ uint32_t best = 0;
+ uint32_t start;
+ uint32_t count;
+ uint32_t index;
unsigned int tag;
EFI_STATUS efirc;
int rc;
- /* Check segment number */
- if ( root->SegmentNumber != segment )
- return -ENOENT;
+ /* Return empty range on error */
+ range->start = 0;
+ range->count = 0;
+
+ /* Open root bridge I/O protocol */
+ if ( ( efirc = bs->OpenProtocol ( handle,
+ &efi_pci_root_bridge_io_protocol_guid,
+ &root.interface, efi_image_handle, handle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( pci, "EFIPCI " PCI_FMT " cannot open %s: %s\n",
+ PCI_ARGS ( pci ), efi_handle_name ( handle ),
+ strerror ( rc ) );
+ goto err_open;
+ }
/* Get ACPI resource descriptors */
- if ( ( efirc = root->Configuration ( root, &u.raw ) ) != 0 ) {
+ if ( ( efirc = root.root->Configuration ( root.root,
+ &acpi.raw ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( pci, "EFIPCI " PCI_FMT " cannot get configuration for "
"%s: %s\n", PCI_ARGS ( pci ),
efi_handle_name ( handle ), strerror ( rc ) );
- return rc;
+ goto err_config;
}
- /* Assume success if no bus number range descriptors are found */
- rc = 0;
-
/* Parse resource descriptors */
- for ( ; ( ( tag = acpi_resource_tag ( u.res ) ) != ACPI_END_RESOURCE ) ;
- u.res = acpi_resource_next ( u.res ) ) {
+ for ( ; ( ( tag = acpi_resource_tag ( acpi.res ) ) !=
+ ACPI_END_RESOURCE ) ;
+ acpi.res = acpi_resource_next ( acpi.res ) ) {
/* Ignore anything other than a bus number range descriptor */
if ( tag != ACPI_QWORD_ADDRESS_SPACE_RESOURCE )
continue;
- if ( u.res->qword.type != ACPI_ADDRESS_TYPE_BUS )
+ if ( acpi.res->qword.type != ACPI_ADDRESS_TYPE_BUS )
continue;
- /* Check for a matching bus number */
- start = le64_to_cpu ( u.res->qword.min );
- end = ( start + le64_to_cpu ( u.res->qword.len ) );
- if ( ( bus >= start ) && ( bus < end ) )
- return 0;
+ /* Get range for this descriptor */
+ start = PCI_BUSDEVFN ( root.root->SegmentNumber,
+ le64_to_cpu ( acpi.res->qword.min ),
+ 0, 0 );
+ count = PCI_BUSDEVFN ( 0, le64_to_cpu ( acpi.res->qword.len ),
+ 0, 0 );
+ DBGC2 ( pci, "EFIPCI " PCI_FMT " found %04x:[%02x-%02x] via "
+ "%s\n", PCI_ARGS ( pci ), root.root->SegmentNumber,
+ PCI_BUS ( start ), PCI_BUS ( start + count - 1 ),
+ efi_handle_name ( handle ) );
+
+ /* Check for a matching or new closest range */
+ index = ( pci->busdevfn - start );
+ if ( ( index < count ) || ( index > best ) ) {
+ range->start = start;
+ range->count = count;
+ best = index;
+ }
- /* We have seen at least one non-matching range
- * descriptor, so assume failure unless we find a
- * subsequent match.
- */
- rc = -ENOENT;
+ /* Stop if this range contains the target bus:dev.fn address */
+ if ( index < count )
+ break;
+ }
+
+ /* If no range descriptors were seen, assume that the root
+ * bridge has a single bus.
+ */
+ if ( ! range->count ) {
+ range->start = PCI_BUSDEVFN ( root.root->SegmentNumber,
+ 0, 0, 0 );
+ range->count = PCI_BUSDEVFN ( 0, 1, 0, 0 );
}
+ /* Success */
+ rc = 0;
+
+ err_config:
+ bs->CloseProtocol ( handle, &efi_pci_root_bridge_io_protocol_guid,
+ efi_image_handle, handle );
+ err_open:
return rc;
}
/**
- * Open EFI PCI root bridge I/O protocol
+ * Find closest bus:dev.fn address range within any root bridge
*
- * @v pci PCI device
- * @ret handle EFI PCI root bridge handle
- * @ret root EFI PCI root bridge I/O protocol, or NULL if not found
+ * @v pci Starting PCI device
+ * @v range PCI bus:dev.fn address range to fill in
+ * @v handle PCI root bridge I/O handle to fill in
* @ret rc Return status code
*/
-static int efipci_root_open ( struct pci_device *pci, EFI_HANDLE *handle,
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **root ) {
+static int efipci_discover_any ( struct pci_device *pci,
+ struct pci_range *range,
+ EFI_HANDLE *handle ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ uint32_t best = 0;
+ uint32_t index;
+ struct pci_range tmp;
EFI_HANDLE *handles;
UINTN num_handles;
- union {
- void *interface;
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root;
- } u;
- EFI_STATUS efirc;
UINTN i;
+ EFI_STATUS efirc;
int rc;
- /* Enumerate all handles */
+ /* Return an empty range and no handle on error */
+ range->start = 0;
+ range->count = 0;
+ *handle = NULL;
+
+ /* Enumerate all root bridge I/O protocol handles */
if ( ( efirc = bs->LocateHandleBuffer ( ByProtocol,
&efi_pci_root_bridge_io_protocol_guid,
NULL, &num_handles, &handles ) ) != 0 ) {
@@ -157,38 +205,102 @@ static int efipci_root_open ( struct pci_device *pci, EFI_HANDLE *handle,
goto err_locate;
}
- /* Look for matching root bridge I/O protocol */
+ /* Iterate over all root bridge I/O protocols */
for ( i = 0 ; i < num_handles ; i++ ) {
- *handle = handles[i];
- if ( ( efirc = bs->OpenProtocol ( *handle,
- &efi_pci_root_bridge_io_protocol_guid,
- &u.interface, efi_image_handle, *handle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
- rc = -EEFI ( efirc );
- DBGC ( pci, "EFIPCI " PCI_FMT " cannot open %s: %s\n",
- PCI_ARGS ( pci ), efi_handle_name ( *handle ),
- strerror ( rc ) );
+
+ /* Get matching or closest range for this root bridge */
+ if ( ( rc = efipci_discover_one ( pci, handles[i],
+ &tmp ) ) != 0 )
continue;
+
+ /* Check for a matching or new closest range */
+ index = ( pci->busdevfn - tmp.start );
+ if ( ( index < tmp.count ) || ( index > best ) ) {
+ range->start = tmp.start;
+ range->count = tmp.count;
+ best = index;
}
- if ( efipci_root_match ( pci, *handle, u.root ) == 0 ) {
- *root = u.root;
- bs->FreePool ( handles );
- return 0;
+
+ /* Stop if this range contains the target bus:dev.fn address */
+ if ( index < tmp.count ) {
+ *handle = handles[i];
+ break;
}
- bs->CloseProtocol ( *handle,
- &efi_pci_root_bridge_io_protocol_guid,
- efi_image_handle, *handle );
}
- DBGC ( pci, "EFIPCI " PCI_FMT " found no root bridge\n",
- PCI_ARGS ( pci ) );
- rc = -ENOENT;
+ /* Check for a range containing the target bus:dev.fn address */
+ if ( ! *handle ) {
+ rc = -ENOENT;
+ goto err_range;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_range:
bs->FreePool ( handles );
err_locate:
return rc;
}
/**
+ * Find next PCI bus:dev.fn address range in system
+ *
+ * @v busdevfn Starting PCI bus:dev.fn address
+ * @v range PCI bus:dev.fn address range to fill in
+ */
+static void efipci_discover ( uint32_t busdevfn, struct pci_range *range ) {
+ struct pci_device pci;
+ EFI_HANDLE handle;
+
+ /* Find range */
+ memset ( &pci, 0, sizeof ( pci ) );
+ pci_init ( &pci, busdevfn );
+ efipci_discover_any ( &pci, range, &handle );
+}
+
+/**
+ * Open EFI PCI root bridge I/O protocol
+ *
+ * @v pci PCI device
+ * @ret handle EFI PCI root bridge handle
+ * @ret root EFI PCI root bridge I/O protocol, or NULL if not found
+ * @ret rc Return status code
+ */
+static int efipci_root_open ( struct pci_device *pci, EFI_HANDLE *handle,
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **root ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct pci_range tmp;
+ union {
+ void *interface;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root;
+ } u;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Find matching root bridge I/O protocol handle */
+ if ( ( rc = efipci_discover_any ( pci, &tmp, handle ) ) != 0 )
+ return rc;
+
+ /* (Re)open PCI root bridge I/O protocol */
+ if ( ( efirc = bs->OpenProtocol ( *handle,
+ &efi_pci_root_bridge_io_protocol_guid,
+ &u.interface, efi_image_handle, *handle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( pci, "EFIPCI " PCI_FMT " cannot open %s: %s\n",
+ PCI_ARGS ( pci ), efi_handle_name ( *handle ),
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Return opened protocol */
+ *root = u.root;
+
+ return 0;
+}
+
+/**
* Close EFI PCI root bridge I/O protocol
*
* @v handle EFI PCI root bridge handle
@@ -362,7 +474,8 @@ void * efipci_ioremap ( struct pci_device *pci, unsigned long bus_addr,
return ioremap ( bus_addr, len );
}
-PROVIDE_PCIAPI_INLINE ( efi, pci_discover );
+PROVIDE_PCIAPI_INLINE ( efi, pci_can_probe );
+PROVIDE_PCIAPI ( efi, pci_discover, efipci_discover );
PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_word );
PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_dword );
diff --git a/src/interface/linux/linux_pci.c b/src/interface/linux/linux_pci.c
index 3008447..a3a0828 100644
--- a/src/interface/linux/linux_pci.c
+++ b/src/interface/linux/linux_pci.c
@@ -188,6 +188,7 @@ int linux_pci_write ( struct pci_device *pci, unsigned long where,
return rc;
}
+PROVIDE_PCIAPI_INLINE ( linux, pci_can_probe );
PROVIDE_PCIAPI_INLINE ( linux, pci_discover );
PROVIDE_PCIAPI_INLINE ( linux, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( linux, pci_read_config_word );
diff --git a/src/net/tls.c b/src/net/tls.c
index 5f89be4..ded100d 100644
--- a/src/net/tls.c
+++ b/src/net/tls.c
@@ -251,8 +251,8 @@ static void tls_set_uint24 ( tls24_t *field24, unsigned long value ) {
* @ret is_ready TLS connection is ready
*/
static int tls_ready ( struct tls_connection *tls ) {
- return ( ( ! is_pending ( &tls->client_negotiation ) ) &&
- ( ! is_pending ( &tls->server_negotiation ) ) );
+ return ( ( ! is_pending ( &tls->client.negotiation ) ) &&
+ ( ! is_pending ( &tls->server.negotiation ) ) );
}
/**
@@ -382,21 +382,21 @@ static void free_tls ( struct refcnt *refcnt ) {
/* Free dynamically-allocated resources */
free ( tls->new_session_ticket );
- tls_clear_cipher ( tls, &tls->tx_cipherspec );
- tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
- tls_clear_cipher ( tls, &tls->rx_cipherspec );
- tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
- free ( tls->server_key );
+ tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
+ tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
+ tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
+ tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
+ free ( tls->server.exchange );
free ( tls->handshake_ctx );
- list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) {
+ list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
list_del ( &iobuf->list );
free_iob ( iobuf );
}
- free_iob ( tls->rx_handshake );
- x509_chain_put ( tls->certs );
- x509_chain_put ( tls->chain );
- x509_root_put ( tls->root );
- privkey_put ( tls->key );
+ free_iob ( tls->rx.handshake );
+ privkey_put ( tls->client.key );
+ x509_chain_put ( tls->client.chain );
+ x509_chain_put ( tls->server.chain );
+ x509_root_put ( tls->server.root );
/* Drop reference to session */
assert ( list_empty ( &tls->list ) );
@@ -415,17 +415,17 @@ static void free_tls ( struct refcnt *refcnt ) {
static void tls_close ( struct tls_connection *tls, int rc ) {
/* Remove pending operations, if applicable */
- pending_put ( &tls->client_negotiation );
- pending_put ( &tls->server_negotiation );
- pending_put ( &tls->validation );
+ pending_put ( &tls->client.negotiation );
+ pending_put ( &tls->server.negotiation );
+ pending_put ( &tls->server.validation );
/* Remove process */
- process_del ( &tls->process );
+ process_del ( &tls->tx.process );
/* Close all interfaces */
intf_shutdown ( &tls->cipherstream, rc );
intf_shutdown ( &tls->plainstream, rc );
- intf_shutdown ( &tls->validator, rc );
+ intf_shutdown ( &tls->server.validator, rc );
/* Remove from session */
list_del ( &tls->list );
@@ -640,15 +640,15 @@ static void tls_generate_master_secret ( struct tls_connection *tls,
DBGC ( tls, "TLS %p pre-master-secret:\n", tls );
DBGC_HD ( tls, pre_master_secret, pre_master_secret_len );
DBGC ( tls, "TLS %p client random bytes:\n", tls );
- DBGC_HD ( tls, &tls->client_random, sizeof ( tls->client_random ) );
+ DBGC_HD ( tls, &tls->client.random, sizeof ( tls->client.random ) );
DBGC ( tls, "TLS %p server random bytes:\n", tls );
- DBGC_HD ( tls, &tls->server_random, sizeof ( tls->server_random ) );
+ DBGC_HD ( tls, &tls->server.random, sizeof ( tls->server.random ) );
tls_prf_label ( tls, pre_master_secret, pre_master_secret_len,
&tls->master_secret, sizeof ( tls->master_secret ),
"master secret",
- &tls->client_random, sizeof ( tls->client_random ),
- &tls->server_random, sizeof ( tls->server_random ) );
+ &tls->client.random, sizeof ( tls->client.random ),
+ &tls->server.random, sizeof ( tls->server.random ) );
DBGC ( tls, "TLS %p generated master secret:\n", tls );
DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) );
@@ -662,8 +662,8 @@ static void tls_generate_master_secret ( struct tls_connection *tls,
* The master secret must already be known.
*/
static int tls_generate_keys ( struct tls_connection *tls ) {
- struct tls_cipherspec *tx_cipherspec = &tls->tx_cipherspec_pending;
- struct tls_cipherspec *rx_cipherspec = &tls->rx_cipherspec_pending;
+ struct tls_cipherspec *tx_cipherspec = &tls->tx.cipherspec.pending;
+ struct tls_cipherspec *rx_cipherspec = &tls->rx.cipherspec.pending;
size_t hash_size = tx_cipherspec->suite->mac_len;
size_t key_size = tx_cipherspec->suite->key_len;
size_t iv_size = tx_cipherspec->suite->fixed_iv_len;
@@ -675,8 +675,8 @@ static int tls_generate_keys ( struct tls_connection *tls ) {
/* Generate key block */
tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
key_block, sizeof ( key_block ), "key expansion",
- &tls->server_random, sizeof ( tls->server_random ),
- &tls->client_random, sizeof ( tls->client_random ) );
+ &tls->server.random, sizeof ( tls->server.random ),
+ &tls->client.random, sizeof ( tls->client.random ) );
/* Split key block into portions */
key = key_block;
@@ -856,10 +856,6 @@ tls_find_cipher_suite ( unsigned int cipher_suite ) {
static void tls_clear_cipher ( struct tls_connection *tls __unused,
struct tls_cipherspec *cipherspec ) {
- if ( cipherspec->suite ) {
- pubkey_final ( cipherspec->suite->pubkey,
- cipherspec->pubkey_ctx );
- }
free ( cipherspec->dynamic );
memset ( cipherspec, 0, sizeof ( *cipherspec ) );
cipherspec->suite = &tls_cipher_suite_null;
@@ -876,7 +872,6 @@ static void tls_clear_cipher ( struct tls_connection *tls __unused,
static int tls_set_cipher ( struct tls_connection *tls,
struct tls_cipherspec *cipherspec,
struct tls_cipher_suite *suite ) {
- struct pubkey_algorithm *pubkey = suite->pubkey;
struct cipher_algorithm *cipher = suite->cipher;
size_t total;
void *dynamic;
@@ -885,8 +880,7 @@ static int tls_set_cipher ( struct tls_connection *tls,
tls_clear_cipher ( tls, cipherspec );
/* Allocate dynamic storage */
- total = ( pubkey->ctxsize + cipher->ctxsize + suite->mac_len +
- suite->fixed_iv_len );
+ total = ( cipher->ctxsize + suite->mac_len + suite->fixed_iv_len );
dynamic = zalloc ( total );
if ( ! dynamic ) {
DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
@@ -896,7 +890,6 @@ static int tls_set_cipher ( struct tls_connection *tls,
/* Assign storage */
cipherspec->dynamic = dynamic;
- cipherspec->pubkey_ctx = dynamic; dynamic += pubkey->ctxsize;
cipherspec->cipher_ctx = dynamic; dynamic += cipher->ctxsize;
cipherspec->mac_secret = dynamic; dynamic += suite->mac_len;
cipherspec->fixed_iv = dynamic; dynamic += suite->fixed_iv_len;
@@ -936,10 +929,10 @@ static int tls_select_cipher ( struct tls_connection *tls,
return rc;
/* Set ciphers */
- if ( ( rc = tls_set_cipher ( tls, &tls->tx_cipherspec_pending,
+ if ( ( rc = tls_set_cipher ( tls, &tls->tx.cipherspec.pending,
suite ) ) != 0 )
return rc;
- if ( ( rc = tls_set_cipher ( tls, &tls->rx_cipherspec_pending,
+ if ( ( rc = tls_set_cipher ( tls, &tls->rx.cipherspec.pending,
suite ) ) != 0 )
return rc;
@@ -955,22 +948,20 @@ static int tls_select_cipher ( struct tls_connection *tls,
* Activate next cipher suite
*
* @v tls TLS connection
- * @v pending Pending cipher specification
- * @v active Active cipher specification to replace
+ * @v pair Cipher specification pair
* @ret rc Return status code
*/
static int tls_change_cipher ( struct tls_connection *tls,
- struct tls_cipherspec *pending,
- struct tls_cipherspec *active ) {
+ struct tls_cipherspec_pair *pair ) {
/* Sanity check */
- if ( pending->suite == &tls_cipher_suite_null ) {
+ if ( pair->pending.suite == &tls_cipher_suite_null ) {
DBGC ( tls, "TLS %p refusing to use null cipher\n", tls );
return -ENOTSUP_NULL;
}
- tls_clear_cipher ( tls, active );
- memswap ( active, pending, sizeof ( *active ) );
+ tls_clear_cipher ( tls, &pair->active );
+ memswap ( &pair->active, &pair->pending, sizeof ( pair->active ) );
return 0;
}
@@ -1088,7 +1079,7 @@ tls_find_named_curve ( unsigned int named_curve ) {
* @v tls TLS connection
*/
static void tls_tx_resume ( struct tls_connection *tls ) {
- process_add ( &tls->process );
+ process_add ( &tls->tx.process );
}
/**
@@ -1111,16 +1102,16 @@ static void tls_tx_resume_all ( struct tls_session *session ) {
static void tls_restart ( struct tls_connection *tls ) {
/* Sanity check */
- assert ( ! tls->tx_pending );
- assert ( ! is_pending ( &tls->client_negotiation ) );
- assert ( ! is_pending ( &tls->server_negotiation ) );
- assert ( ! is_pending ( &tls->validation ) );
+ assert ( ! tls->tx.pending );
+ assert ( ! is_pending ( &tls->client.negotiation ) );
+ assert ( ! is_pending ( &tls->server.negotiation ) );
+ assert ( ! is_pending ( &tls->server.validation ) );
/* (Re)start negotiation */
- tls->tx_pending = TLS_TX_CLIENT_HELLO;
+ tls->tx.pending = TLS_TX_CLIENT_HELLO;
tls_tx_resume ( tls );
- pending_get ( &tls->client_negotiation );
- pending_get ( &tls->server_negotiation );
+ pending_get ( &tls->client.negotiation );
+ pending_get ( &tls->server.negotiation );
}
/**
@@ -1239,7 +1230,7 @@ static int tls_client_hello ( struct tls_connection *tls,
htonl ( sizeof ( hello ) -
sizeof ( hello.type_length ) ) );
hello.version = htons ( TLS_VERSION_MAX );
- memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) );
+ memcpy ( &hello.random, &tls->client.random, sizeof ( hello.random ) );
hello.session_id_len = tls->session_id_len;
memcpy ( hello.session_id, tls->session_id,
sizeof ( hello.session_id ) );
@@ -1346,7 +1337,7 @@ static int tls_send_certificate ( struct tls_connection *tls ) {
/* Calculate length of client certificates */
len = 0;
- list_for_each_entry ( link, &tls->certs->links, list ) {
+ list_for_each_entry ( link, &tls->client.chain->links, list ) {
cert = link->cert;
len += ( sizeof ( *certificate ) + cert->raw.len );
DBGC ( tls, "TLS %p sending client certificate %s\n",
@@ -1367,7 +1358,7 @@ static int tls_send_certificate ( struct tls_connection *tls ) {
sizeof ( certificates->type_length ) ) );
tls_set_uint24 ( &certificates->length, len );
certificate = &certificates->certificates[0];
- list_for_each_entry ( link, &tls->certs->links, list ) {
+ list_for_each_entry ( link, &tls->client.chain->links, list ) {
cert = link->cert;
tls_set_uint24 ( &certificate->length, cert->raw.len );
memcpy ( certificate->data, cert->raw.data, cert->raw.len );
@@ -1392,9 +1383,9 @@ static int tls_send_certificate ( struct tls_connection *tls ) {
* @ret rc Return status code
*/
static int tls_send_client_key_exchange_pubkey ( struct tls_connection *tls ) {
- struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
+ struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
- size_t max_len = pubkey_max_len ( pubkey, cipherspec->pubkey_ctx );
+ size_t max_len = pubkey_max_len ( pubkey, &tls->server.key );
struct {
uint16_t version;
uint8_t random[46];
@@ -1421,8 +1412,8 @@ static int tls_send_client_key_exchange_pubkey ( struct tls_connection *tls ) {
/* Encrypt pre-master secret using server's public key */
memset ( &key_xchg, 0, sizeof ( key_xchg ) );
- len = pubkey_encrypt ( pubkey, cipherspec->pubkey_ctx,
- &pre_master_secret, sizeof ( pre_master_secret ),
+ len = pubkey_encrypt ( pubkey, &tls->server.key, &pre_master_secret,
+ sizeof ( pre_master_secret ),
key_xchg.encrypted_pre_master_secret );
if ( len < 0 ) {
rc = len;
@@ -1458,7 +1449,7 @@ struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm = {
*/
static int tls_verify_dh_params ( struct tls_connection *tls,
size_t param_len ) {
- struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
+ struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
struct pubkey_algorithm *pubkey;
struct digest_algorithm *digest;
int use_sig_hash = tls_version ( tls, TLS_VERSION_TLS_1_2 );
@@ -1472,9 +1463,9 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
int rc;
/* Signature follows parameters */
- assert ( param_len <= tls->server_key_len );
- data = ( tls->server_key + param_len );
- remaining = ( tls->server_key_len - param_len );
+ assert ( param_len <= tls->server.exchange_len );
+ data = ( tls->server.exchange + param_len );
+ remaining = ( tls->server.exchange_len - param_len );
/* Parse signature from ServerKeyExchange */
sig = data;
@@ -1483,7 +1474,8 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
sizeof ( *sig ) ) ) ) {
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
tls );
- DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
+ DBGC_HDA ( tls, 0, tls->server.exchange,
+ tls->server.exchange_len );
return -EINVAL_KEY_EXCHANGE;
}
@@ -1516,21 +1508,21 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
/* Calculate digest */
digest_init ( digest, ctx );
- digest_update ( digest, ctx, &tls->client_random,
- sizeof ( tls->client_random ) );
- digest_update ( digest, ctx, tls->server_random,
- sizeof ( tls->server_random ) );
- digest_update ( digest, ctx, tls->server_key, param_len );
+ digest_update ( digest, ctx, &tls->client.random,
+ sizeof ( tls->client.random ) );
+ digest_update ( digest, ctx, tls->server.random,
+ sizeof ( tls->server.random ) );
+ digest_update ( digest, ctx, tls->server.exchange, param_len );
digest_final ( digest, ctx, hash );
/* Verify signature */
- if ( ( rc = pubkey_verify ( pubkey, cipherspec->pubkey_ctx,
+ if ( ( rc = pubkey_verify ( pubkey, &tls->server.key,
digest, hash, signature,
signature_len ) ) != 0 ) {
DBGC ( tls, "TLS %p ServerKeyExchange failed "
"verification\n", tls );
- DBGC_HDA ( tls, 0, tls->server_key,
- tls->server_key_len );
+ DBGC_HDA ( tls, 0, tls->server.exchange,
+ tls->server.exchange_len );
return -EPERM_KEY_EXCHANGE;
}
}
@@ -1545,7 +1537,7 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
* @ret rc Return status code
*/
static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
- uint8_t private[ sizeof ( tls->client_random.random ) ];
+ uint8_t private[ sizeof ( tls->client.random.random ) ];
const struct {
uint16_t len;
uint8_t data[0];
@@ -1558,8 +1550,8 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
int rc;
/* Parse ServerKeyExchange */
- data = tls->server_key;
- remaining = tls->server_key_len;
+ data = tls->server.exchange;
+ remaining = tls->server.exchange_len;
for ( i = 0 ; i < ( sizeof ( dh_val ) / sizeof ( dh_val[0] ) ) ; i++ ){
dh_val[i] = data;
if ( ( sizeof ( *dh_val[i] ) > remaining ) ||
@@ -1567,8 +1559,8 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
sizeof ( *dh_val[i] ) ) )){
DBGC ( tls, "TLS %p received underlength "
"ServerKeyExchange\n", tls );
- DBGC_HDA ( tls, 0, tls->server_key,
- tls->server_key_len );
+ DBGC_HDA ( tls, 0, tls->server.exchange,
+ tls->server.exchange_len );
rc = -EINVAL_KEY_EXCHANGE;
goto err_header;
}
@@ -1576,7 +1568,7 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
data += frag_len;
remaining -= frag_len;
}
- param_len = ( tls->server_key_len - remaining );
+ param_len = ( tls->server.exchange_len - remaining );
/* Verify parameter signature */
if ( ( rc = tls_verify_dh_params ( tls, param_len ) ) != 0 )
@@ -1681,12 +1673,14 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
int rc;
/* Parse ServerKeyExchange record */
- ecdh = tls->server_key;
- if ( ( sizeof ( *ecdh ) > tls->server_key_len ) ||
- ( ecdh->public_len > ( tls->server_key_len - sizeof ( *ecdh ) ))){
+ ecdh = tls->server.exchange;
+ if ( ( sizeof ( *ecdh ) > tls->server.exchange_len ) ||
+ ( ecdh->public_len > ( tls->server.exchange_len -
+ sizeof ( *ecdh ) ) ) ) {
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
tls );
- DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
+ DBGC_HDA ( tls, 0, tls->server.exchange,
+ tls->server.exchange_len );
return -EINVAL_KEY_EXCHANGE;
}
param_len = ( sizeof ( *ecdh ) + ecdh->public_len );
@@ -1699,14 +1693,16 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
if ( ecdh->curve_type != TLS_NAMED_CURVE_TYPE ) {
DBGC ( tls, "TLS %p unsupported curve type %d\n",
tls, ecdh->curve_type );
- DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
+ DBGC_HDA ( tls, 0, tls->server.exchange,
+ tls->server.exchange_len );
return -ENOTSUP_CURVE;
}
curve = tls_find_named_curve ( ecdh->named_curve );
if ( ! curve ) {
DBGC ( tls, "TLS %p unsupported named curve %d\n",
tls, ntohs ( ecdh->named_curve ) );
- DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
+ DBGC_HDA ( tls, 0, tls->server.exchange,
+ tls->server.exchange_len );
return -ENOTSUP_CURVE;
}
@@ -1714,7 +1710,8 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
if ( ecdh->public_len != curve->curve->keysize ) {
DBGC ( tls, "TLS %p invalid %s key\n",
tls, curve->curve->name );
- DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
+ DBGC_HDA ( tls, 0, tls->server.exchange,
+ tls->server.exchange_len );
return -EINVAL_KEY_EXCHANGE;
}
@@ -1783,7 +1780,7 @@ struct tls_key_exchange_algorithm tls_ecdhe_exchange_algorithm = {
* @ret rc Return status code
*/
static int tls_send_client_key_exchange ( struct tls_connection *tls ) {
- struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
+ struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.pending;
struct tls_cipher_suite *suite = cipherspec->suite;
int rc;
@@ -1812,24 +1809,16 @@ static int tls_send_client_key_exchange ( struct tls_connection *tls ) {
*/
static int tls_send_certificate_verify ( struct tls_connection *tls ) {
struct digest_algorithm *digest = tls->handshake_digest;
- struct x509_certificate *cert = x509_first ( tls->certs );
+ struct x509_certificate *cert = x509_first ( tls->client.chain );
struct pubkey_algorithm *pubkey = cert->signature_algorithm->pubkey;
- struct asn1_cursor *key = privkey_cursor ( tls->key );
+ struct asn1_cursor *key = privkey_cursor ( tls->client.key );
uint8_t digest_out[ digest->digestsize ];
- uint8_t ctx[ pubkey->ctxsize ];
struct tls_signature_hash_algorithm *sig_hash = NULL;
int rc;
/* Generate digest to be signed */
tls_verify_handshake ( tls, digest_out );
- /* Initialise public-key algorithm */
- if ( ( rc = pubkey_init ( pubkey, ctx, key->data, key->len ) ) != 0 ) {
- DBGC ( tls, "TLS %p could not initialise %s client private "
- "key: %s\n", tls, pubkey->name, strerror ( rc ) );
- goto err_pubkey_init;
- }
-
/* TLSv1.2 and later use explicit algorithm identifiers */
if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
@@ -1844,7 +1833,7 @@ static int tls_send_certificate_verify ( struct tls_connection *tls ) {
/* Generate and transmit record */
{
- size_t max_len = pubkey_max_len ( pubkey, ctx );
+ size_t max_len = pubkey_max_len ( pubkey, key );
int use_sig_hash = ( ( sig_hash == NULL ) ? 0 : 1 );
struct {
uint32_t type_length;
@@ -1856,7 +1845,7 @@ static int tls_send_certificate_verify ( struct tls_connection *tls ) {
int len;
/* Sign digest */
- len = pubkey_sign ( pubkey, ctx, digest, digest_out,
+ len = pubkey_sign ( pubkey, key, digest, digest_out,
certificate_verify.signature );
if ( len < 0 ) {
rc = len;
@@ -1889,8 +1878,6 @@ static int tls_send_certificate_verify ( struct tls_connection *tls ) {
err_pubkey_sign:
err_sig_hash:
- pubkey_final ( pubkey, ctx );
- err_pubkey_init:
return rc;
}
@@ -1946,7 +1933,7 @@ static int tls_send_finished ( struct tls_connection *tls ) {
return rc;
/* Mark client as finished */
- pending_put ( &tls->client_negotiation );
+ pending_put ( &tls->client.negotiation );
return 0;
}
@@ -1976,13 +1963,12 @@ static int tls_new_change_cipher ( struct tls_connection *tls,
iob_pull ( iobuf, sizeof ( *change_cipher ) );
/* Change receive cipher spec */
- if ( ( rc = tls_change_cipher ( tls, &tls->rx_cipherspec_pending,
- &tls->rx_cipherspec ) ) != 0 ) {
+ if ( ( rc = tls_change_cipher ( tls, &tls->rx.cipherspec ) ) != 0 ) {
DBGC ( tls, "TLS %p could not activate RX cipher: %s\n",
tls, strerror ( rc ) );
return rc;
}
- tls->rx_seq = ~( ( uint64_t ) 0 );
+ tls->rx.seq = ~( ( uint64_t ) 0 );
return 0;
}
@@ -2188,8 +2174,8 @@ static int tls_new_server_hello ( struct tls_connection *tls,
return rc;
/* Copy out server random bytes */
- memcpy ( &tls->server_random, &hello_a->random,
- sizeof ( tls->server_random ) );
+ memcpy ( &tls->server.random, &hello_a->random,
+ sizeof ( tls->server.random ) );
/* Check session ID */
if ( hello_a->session_id_len &&
@@ -2309,12 +2295,13 @@ static int tls_parse_chain ( struct tls_connection *tls,
int rc;
/* Free any existing certificate chain */
- x509_chain_put ( tls->chain );
- tls->chain = NULL;
+ memset ( &tls->server.key, 0, sizeof ( tls->server.key ) );
+ x509_chain_put ( tls->server.chain );
+ tls->server.chain = NULL;
/* Create certificate chain */
- tls->chain = x509_alloc_chain();
- if ( ! tls->chain ) {
+ tls->server.chain = x509_alloc_chain();
+ if ( ! tls->server.chain ) {
rc = -ENOMEM_CHAIN;
goto err_alloc_chain;
}
@@ -2346,14 +2333,15 @@ static int tls_parse_chain ( struct tls_connection *tls,
record_len = ( sizeof ( *certificate ) + certificate_len );
/* Add certificate to chain */
- if ( ( rc = x509_append_raw ( tls->chain, certificate->data,
+ if ( ( rc = x509_append_raw ( tls->server.chain,
+ certificate->data,
certificate_len ) ) != 0 ) {
DBGC ( tls, "TLS %p could not append certificate: %s\n",
tls, strerror ( rc ) );
DBGC_HDA ( tls, 0, data, remaining );
goto err_parse;
}
- cert = x509_last ( tls->chain );
+ cert = x509_last ( tls->server.chain );
DBGC ( tls, "TLS %p found certificate %s\n",
tls, x509_name ( cert ) );
@@ -2367,8 +2355,9 @@ static int tls_parse_chain ( struct tls_connection *tls,
err_parse:
err_overlength:
err_underlength:
- x509_chain_put ( tls->chain );
- tls->chain = NULL;
+ memset ( &tls->server.key, 0, sizeof ( tls->server.key ) );
+ x509_chain_put ( tls->server.chain );
+ tls->server.chain = NULL;
err_alloc_chain:
return rc;
}
@@ -2425,12 +2414,12 @@ static int tls_new_server_key_exchange ( struct tls_connection *tls,
const void *data, size_t len ) {
/* Free any existing server key exchange record */
- free ( tls->server_key );
- tls->server_key_len = 0;
+ free ( tls->server.exchange );
+ tls->server.exchange_len = 0;
/* Allocate copy of server key exchange record */
- tls->server_key = malloc ( len );
- if ( ! tls->server_key )
+ tls->server.exchange = malloc ( len );
+ if ( ! tls->server.exchange )
return -ENOMEM;
/* Store copy of server key exchange record for later
@@ -2438,8 +2427,8 @@ static int tls_new_server_key_exchange ( struct tls_connection *tls,
* since the certificate validation will not yet have
* completed.
*/
- memcpy ( tls->server_key, data, len );
- tls->server_key_len = len;
+ memcpy ( tls->server.exchange, data, len );
+ tls->server.exchange_len = len;
return 0;
}
@@ -2463,11 +2452,11 @@ static int tls_new_certificate_request ( struct tls_connection *tls,
*/
/* Free any existing client certificate chain */
- x509_chain_put ( tls->certs );
- tls->certs = NULL;
+ x509_chain_put ( tls->client.chain );
+ tls->client.chain = NULL;
/* Determine client certificate to be sent */
- cert = certstore_find_key ( tls->key );
+ cert = x509_find_key ( NULL, tls->client.key );
if ( ! cert ) {
DBGC ( tls, "TLS %p could not find certificate corresponding "
"to private key\n", tls );
@@ -2479,18 +2468,18 @@ static int tls_new_certificate_request ( struct tls_connection *tls,
tls, x509_name ( cert ) );
/* Create client certificate chain */
- tls->certs = x509_alloc_chain();
- if ( ! tls->certs ) {
+ tls->client.chain = x509_alloc_chain();
+ if ( ! tls->client.chain ) {
rc = -ENOMEM;
goto err_alloc;
}
/* Append client certificate to chain */
- if ( ( rc = x509_append ( tls->certs, cert ) ) != 0 )
+ if ( ( rc = x509_append ( tls->client.chain, cert ) ) != 0 )
goto err_append;
/* Append any relevant issuer certificates */
- if ( ( rc = x509_auto_append ( tls->certs, &certstore ) ) != 0 )
+ if ( ( rc = x509_auto_append ( tls->client.chain, &certstore ) ) != 0 )
goto err_auto_append;
/* Drop local reference to client certificate */
@@ -2500,8 +2489,8 @@ static int tls_new_certificate_request ( struct tls_connection *tls,
err_auto_append:
err_append:
- x509_chain_put ( tls->certs );
- tls->certs = NULL;
+ x509_chain_put ( tls->client.chain );
+ tls->client.chain = NULL;
err_alloc:
x509_put ( cert );
err_find:
@@ -2532,13 +2521,14 @@ static int tls_new_server_hello_done ( struct tls_connection *tls,
}
/* Begin certificate validation */
- if ( ( rc = create_validator ( &tls->validator, tls->chain,
- tls->root ) ) != 0 ) {
+ if ( ( rc = create_validator ( &tls->server.validator,
+ tls->server.chain,
+ tls->server.root ) ) != 0 ) {
DBGC ( tls, "TLS %p could not start certificate validation: "
"%s\n", tls, strerror ( rc ) );
return rc;
}
- pending_get ( &tls->validation );
+ pending_get ( &tls->server.validation );
return 0;
}
@@ -2580,14 +2570,14 @@ static int tls_new_finished ( struct tls_connection *tls,
}
/* Mark server as finished */
- pending_put ( &tls->server_negotiation );
+ pending_put ( &tls->server.negotiation );
/* If we are resuming a session (i.e. if the server Finished
* arrives before the client Finished is sent), then schedule
* transmission of Change Cipher and Finished.
*/
- if ( is_pending ( &tls->client_negotiation ) ) {
- tls->tx_pending |= ( TLS_TX_CHANGE_CIPHER | TLS_TX_FINISHED );
+ if ( is_pending ( &tls->client.negotiation ) ) {
+ tls->tx.pending |= ( TLS_TX_CHANGE_CIPHER | TLS_TX_FINISHED );
tls_tx_resume ( tls );
}
@@ -2788,7 +2778,7 @@ static int tls_new_record ( struct tls_connection *tls, unsigned int type,
break;
case TLS_TYPE_HANDSHAKE:
handler = tls_new_handshake;
- iobuf = &tls->rx_handshake;
+ iobuf = &tls->rx.handshake;
break;
default:
DBGC ( tls, "TLS %p unknown record type %d\n", tls, type );
@@ -2935,7 +2925,7 @@ static void tls_hmac_list ( struct tls_cipherspec *cipherspec,
*/
static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type,
const void *data, size_t len ) {
- struct tls_cipherspec *cipherspec = &tls->tx_cipherspec;
+ struct tls_cipherspec *cipherspec = &tls->tx.cipherspec.active;
struct tls_cipher_suite *suite = cipherspec->suite;
struct cipher_algorithm *cipher = suite->cipher;
struct digest_algorithm *digest = suite->digest;
@@ -2962,7 +2952,7 @@ static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type,
}
/* Construct authentication data */
- authhdr.seq = cpu_to_be64 ( tls->tx_seq );
+ authhdr.seq = cpu_to_be64 ( tls->tx.seq );
authhdr.header.type = type;
authhdr.header.version = htons ( tls->version );
authhdr.header.length = htons ( len );
@@ -3046,7 +3036,7 @@ static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type,
}
/* Update TX state machine to next record */
- tls->tx_seq += 1;
+ tls->tx.seq += 1;
assert ( plaintext == NULL );
assert ( ciphertext == NULL );
@@ -3107,7 +3097,7 @@ static int tls_verify_padding ( struct tls_connection *tls,
static int tls_new_ciphertext ( struct tls_connection *tls,
struct tls_header *tlshdr,
struct list_head *rx_data ) {
- struct tls_cipherspec *cipherspec = &tls->rx_cipherspec;
+ struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
struct tls_cipher_suite *suite = cipherspec->suite;
struct cipher_algorithm *cipher = suite->cipher;
struct digest_algorithm *digest = suite->digest;
@@ -3156,7 +3146,7 @@ static int tls_new_ciphertext ( struct tls_connection *tls,
auth = last->tail;
/* Construct authentication data */
- authhdr.seq = cpu_to_be64 ( tls->rx_seq );
+ authhdr.seq = cpu_to_be64 ( tls->rx.seq );
authhdr.header.type = tlshdr->type;
authhdr.header.version = tlshdr->version;
authhdr.header.length = htons ( len );
@@ -3172,7 +3162,7 @@ static int tls_new_ciphertext ( struct tls_connection *tls,
/* Decrypt the received data */
check_len = 0;
- list_for_each_entry ( iobuf, &tls->rx_data, list ) {
+ list_for_each_entry ( iobuf, &tls->rx.data, list ) {
cipher_decrypt ( cipher, cipherspec->cipher_ctx,
iobuf->data, iobuf->data, iob_len ( iobuf ) );
check_len += iob_len ( iobuf );
@@ -3298,8 +3288,8 @@ static int tls_progress ( struct tls_connection *tls,
struct job_progress *progress ) {
/* Return cipherstream or validator progress as applicable */
- if ( is_pending ( &tls->validation ) ) {
- return job_progress ( &tls->validator, progress );
+ if ( is_pending ( &tls->server.validation ) ) {
+ return job_progress ( &tls->server.validator, progress );
} else {
return job_progress ( &tls->cipherstream, progress );
}
@@ -3334,10 +3324,10 @@ static struct interface_descriptor tls_plainstream_desc =
* @ret rc Returned status code
*/
static int tls_newdata_process_header ( struct tls_connection *tls ) {
- struct tls_cipherspec *cipherspec = &tls->rx_cipherspec;
+ struct tls_cipherspec *cipherspec = &tls->rx.cipherspec.active;
struct cipher_algorithm *cipher = cipherspec->suite->cipher;
size_t iv_len = cipherspec->suite->record_iv_len;
- size_t data_len = ntohs ( tls->rx_header.length );
+ size_t data_len = ntohs ( tls->rx.header.length );
size_t remaining = data_len;
size_t frag_len;
size_t reserve;
@@ -3353,7 +3343,7 @@ static int tls_newdata_process_header ( struct tls_connection *tls ) {
remaining += reserve;
/* Allocate data buffers now that we know the length */
- assert ( list_empty ( &tls->rx_data ) );
+ assert ( list_empty ( &tls->rx.data ) );
while ( remaining ) {
/* Calculate fragment length. Ensure that no block is
@@ -3394,16 +3384,16 @@ static int tls_newdata_process_header ( struct tls_connection *tls ) {
reserve = 0;
/* Add I/O buffer to list */
- list_add_tail ( &iobuf->list, &tls->rx_data );
+ list_add_tail ( &iobuf->list, &tls->rx.data );
}
/* Move to data state */
- tls->rx_state = TLS_RX_DATA;
+ tls->rx.state = TLS_RX_DATA;
return 0;
err:
- list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) {
+ list_for_each_entry_safe ( iobuf, tmp, &tls->rx.data, list ) {
list_del ( &iobuf->list );
free_iob ( iobuf );
}
@@ -3421,27 +3411,27 @@ static int tls_newdata_process_data ( struct tls_connection *tls ) {
int rc;
/* Move current buffer to end of list */
- iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list );
+ iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
list_del ( &iobuf->list );
- list_add_tail ( &iobuf->list, &tls->rx_data );
+ list_add_tail ( &iobuf->list, &tls->rx.data );
/* Continue receiving data if any space remains */
- iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list );
+ iobuf = list_first_entry ( &tls->rx.data, struct io_buffer, list );
if ( iob_tailroom ( iobuf ) )
return 0;
/* Process record */
- if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header,
- &tls->rx_data ) ) != 0 )
+ if ( ( rc = tls_new_ciphertext ( tls, &tls->rx.header,
+ &tls->rx.data ) ) != 0 )
return rc;
/* Increment RX sequence number */
- tls->rx_seq += 1;
+ tls->rx.seq += 1;
/* Return to header state */
- assert ( list_empty ( &tls->rx_data ) );
- tls->rx_state = TLS_RX_HEADER;
- iob_unput ( &tls->rx_header_iobuf, sizeof ( tls->rx_header ) );
+ assert ( list_empty ( &tls->rx.data ) );
+ tls->rx.state = TLS_RX_HEADER;
+ iob_unput ( &tls->rx.iobuf, sizeof ( tls->rx.header ) );
return 0;
}
@@ -3480,13 +3470,13 @@ static int tls_cipherstream_deliver ( struct tls_connection *tls,
while ( iob_len ( iobuf ) ) {
/* Select buffer according to current state */
- switch ( tls->rx_state ) {
+ switch ( tls->rx.state ) {
case TLS_RX_HEADER:
- dest = &tls->rx_header_iobuf;
+ dest = &tls->rx.iobuf;
process = tls_newdata_process_header;
break;
case TLS_RX_DATA:
- dest = list_first_entry ( &tls->rx_data,
+ dest = list_first_entry ( &tls->rx.data,
struct io_buffer, list );
assert ( dest != NULL );
process = tls_newdata_process_data;
@@ -3550,15 +3540,13 @@ static struct interface_descriptor tls_cipherstream_desc =
*/
static void tls_validator_done ( struct tls_connection *tls, int rc ) {
struct tls_session *session = tls->session;
- struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
- struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
struct x509_certificate *cert;
/* Mark validation as complete */
- pending_put ( &tls->validation );
+ pending_put ( &tls->server.validation );
/* Close validator interface */
- intf_restart ( &tls->validator, rc );
+ intf_restart ( &tls->server.validator, rc );
/* Check for validation failure */
if ( rc != 0 ) {
@@ -3569,7 +3557,7 @@ static void tls_validator_done ( struct tls_connection *tls, int rc ) {
DBGC ( tls, "TLS %p certificate validation succeeded\n", tls );
/* Extract first certificate */
- cert = x509_first ( tls->chain );
+ cert = x509_first ( tls->server.chain );
assert ( cert != NULL );
/* Verify server name */
@@ -3579,21 +3567,16 @@ static void tls_validator_done ( struct tls_connection *tls, int rc ) {
goto err;
}
- /* Initialise public key algorithm */
- if ( ( rc = pubkey_init ( pubkey, cipherspec->pubkey_ctx,
- cert->subject.public_key.raw.data,
- cert->subject.public_key.raw.len ) ) != 0 ) {
- DBGC ( tls, "TLS %p cannot initialise public key: %s\n",
- tls, strerror ( rc ) );
- goto err;
- }
+ /* Extract the now trusted server public key */
+ memcpy ( &tls->server.key, &cert->subject.public_key.raw,
+ sizeof ( tls->server.key ) );
/* Schedule Client Key Exchange, Change Cipher, and Finished */
- tls->tx_pending |= ( TLS_TX_CLIENT_KEY_EXCHANGE |
+ tls->tx.pending |= ( TLS_TX_CLIENT_KEY_EXCHANGE |
TLS_TX_CHANGE_CIPHER |
TLS_TX_FINISHED );
- if ( tls->certs ) {
- tls->tx_pending |= ( TLS_TX_CERTIFICATE |
+ if ( tls->client.chain ) {
+ tls->tx.pending |= ( TLS_TX_CERTIFICATE |
TLS_TX_CERTIFICATE_VERIFY );
}
tls_tx_resume ( tls );
@@ -3612,7 +3595,8 @@ static struct interface_operation tls_validator_ops[] = {
/** TLS certificate validator interface descriptor */
static struct interface_descriptor tls_validator_desc =
- INTF_DESC ( struct tls_connection, validator, tls_validator_ops );
+ INTF_DESC ( struct tls_connection, server.validator,
+ tls_validator_ops );
/******************************************************************************
*
@@ -3636,7 +3620,7 @@ static void tls_tx_step ( struct tls_connection *tls ) {
return;
/* Send first pending transmission */
- if ( tls->tx_pending & TLS_TX_CLIENT_HELLO ) {
+ if ( tls->tx.pending & TLS_TX_CLIENT_HELLO ) {
/* Serialise server negotiations within a session, to
* provide a consistent view of session IDs and
* session tickets.
@@ -3644,7 +3628,7 @@ static void tls_tx_step ( struct tls_connection *tls ) {
list_for_each_entry ( conn, &session->conn, list ) {
if ( conn == tls )
break;
- if ( is_pending ( &conn->server_negotiation ) )
+ if ( is_pending ( &conn->server.negotiation ) )
return;
}
/* Record or generate session ID and associated master secret */
@@ -3658,8 +3642,8 @@ static void tls_tx_step ( struct tls_connection *tls ) {
} else {
/* No existing session: use a random session ID */
assert ( sizeof ( tls->session_id ) ==
- sizeof ( tls->client_random ) );
- memcpy ( tls->session_id, &tls->client_random,
+ sizeof ( tls->client.random ) );
+ memcpy ( tls->session_id, &tls->client.random,
sizeof ( tls->session_id ) );
tls->session_id_len = sizeof ( tls->session_id );
}
@@ -3669,32 +3653,32 @@ static void tls_tx_step ( struct tls_connection *tls ) {
tls, strerror ( rc ) );
goto err;
}
- tls->tx_pending &= ~TLS_TX_CLIENT_HELLO;
- } else if ( tls->tx_pending & TLS_TX_CERTIFICATE ) {
+ tls->tx.pending &= ~TLS_TX_CLIENT_HELLO;
+ } else if ( tls->tx.pending & TLS_TX_CERTIFICATE ) {
/* Send Certificate */
if ( ( rc = tls_send_certificate ( tls ) ) != 0 ) {
DBGC ( tls, "TLS %p cold not send Certificate: %s\n",
tls, strerror ( rc ) );
goto err;
}
- tls->tx_pending &= ~TLS_TX_CERTIFICATE;
- } else if ( tls->tx_pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
+ tls->tx.pending &= ~TLS_TX_CERTIFICATE;
+ } else if ( tls->tx.pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
/* Send Client Key Exchange */
if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
DBGC ( tls, "TLS %p could not send Client Key "
"Exchange: %s\n", tls, strerror ( rc ) );
goto err;
}
- tls->tx_pending &= ~TLS_TX_CLIENT_KEY_EXCHANGE;
- } else if ( tls->tx_pending & TLS_TX_CERTIFICATE_VERIFY ) {
+ tls->tx.pending &= ~TLS_TX_CLIENT_KEY_EXCHANGE;
+ } else if ( tls->tx.pending & TLS_TX_CERTIFICATE_VERIFY ) {
/* Send Certificate Verify */
if ( ( rc = tls_send_certificate_verify ( tls ) ) != 0 ) {
DBGC ( tls, "TLS %p could not send Certificate "
"Verify: %s\n", tls, strerror ( rc ) );
goto err;
}
- tls->tx_pending &= ~TLS_TX_CERTIFICATE_VERIFY;
- } else if ( tls->tx_pending & TLS_TX_CHANGE_CIPHER ) {
+ tls->tx.pending &= ~TLS_TX_CERTIFICATE_VERIFY;
+ } else if ( tls->tx.pending & TLS_TX_CHANGE_CIPHER ) {
/* Send Change Cipher, and then change the cipher in use */
if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
DBGC ( tls, "TLS %p could not send Change Cipher: "
@@ -3702,28 +3686,27 @@ static void tls_tx_step ( struct tls_connection *tls ) {
goto err;
}
if ( ( rc = tls_change_cipher ( tls,
- &tls->tx_cipherspec_pending,
- &tls->tx_cipherspec )) != 0 ){
+ &tls->tx.cipherspec ) ) != 0 ){
DBGC ( tls, "TLS %p could not activate TX cipher: "
"%s\n", tls, strerror ( rc ) );
goto err;
}
- tls->tx_seq = 0;
- tls->tx_pending &= ~TLS_TX_CHANGE_CIPHER;
- } else if ( tls->tx_pending & TLS_TX_FINISHED ) {
+ tls->tx.seq = 0;
+ tls->tx.pending &= ~TLS_TX_CHANGE_CIPHER;
+ } else if ( tls->tx.pending & TLS_TX_FINISHED ) {
/* Send Finished */
if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
DBGC ( tls, "TLS %p could not send Finished: %s\n",
tls, strerror ( rc ) );
goto err;
}
- tls->tx_pending &= ~TLS_TX_FINISHED;
+ tls->tx.pending &= ~TLS_TX_FINISHED;
}
/* Reschedule process if pending transmissions remain,
* otherwise send notification of a window change.
*/
- if ( tls->tx_pending ) {
+ if ( tls->tx.pending ) {
tls_tx_resume ( tls );
} else {
xfer_window_changed ( &tls->plainstream );
@@ -3737,7 +3720,7 @@ static void tls_tx_step ( struct tls_connection *tls ) {
/** TLS TX process descriptor */
static struct process_descriptor tls_process_desc =
- PROC_DESC_ONCE ( struct tls_connection, process, tls_tx_step );
+ PROC_DESC_ONCE ( struct tls_connection, tx.process, tls_tx_step );
/******************************************************************************
*
@@ -3761,8 +3744,8 @@ static int tls_session ( struct tls_connection *tls, const char *name ) {
/* Find existing matching session, if any */
list_for_each_entry ( session, &tls_sessions, list ) {
if ( ( strcmp ( name, session->name ) == 0 ) &&
- ( tls->root == session->root ) &&
- ( tls->key == session->key ) ) {
+ ( tls->server.root == session->root ) &&
+ ( tls->client.key == session->key ) ) {
ref_get ( &session->refcnt );
tls->session = session;
DBGC ( tls, "TLS %p joining session %s\n", tls, name );
@@ -3781,8 +3764,8 @@ static int tls_session ( struct tls_connection *tls, const char *name ) {
name_copy = ( ( ( void * ) session ) + sizeof ( *session ) );
strcpy ( name_copy, name );
session->name = name_copy;
- session->root = x509_root_get ( tls->root );
- session->key = privkey_get ( tls->key );
+ session->root = x509_root_get ( tls->server.root );
+ session->key = privkey_get ( tls->client.key );
INIT_LIST_HEAD ( &session->conn );
list_add ( &session->list, &tls_sessions );
@@ -3829,23 +3812,23 @@ int add_tls ( struct interface *xfer, const char *name,
INIT_LIST_HEAD ( &tls->list );
intf_init ( &tls->plainstream, &tls_plainstream_desc, &tls->refcnt );
intf_init ( &tls->cipherstream, &tls_cipherstream_desc, &tls->refcnt );
- intf_init ( &tls->validator, &tls_validator_desc, &tls->refcnt );
- process_init_stopped ( &tls->process, &tls_process_desc,
+ intf_init ( &tls->server.validator, &tls_validator_desc, &tls->refcnt );
+ process_init_stopped ( &tls->tx.process, &tls_process_desc,
&tls->refcnt );
- tls->key = privkey_get ( key ? key : &private_key );
- tls->root = x509_root_get ( root ? root : &root_certificates );
+ tls->client.key = privkey_get ( key ? key : &private_key );
+ tls->server.root = x509_root_get ( root ? root : &root_certificates );
tls->version = TLS_VERSION_MAX;
- tls_clear_cipher ( tls, &tls->tx_cipherspec );
- tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
- tls_clear_cipher ( tls, &tls->rx_cipherspec );
- tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
+ tls_clear_cipher ( tls, &tls->tx.cipherspec.active );
+ tls_clear_cipher ( tls, &tls->tx.cipherspec.pending );
+ tls_clear_cipher ( tls, &tls->rx.cipherspec.active );
+ tls_clear_cipher ( tls, &tls->rx.cipherspec.pending );
tls_clear_handshake ( tls );
- tls->client_random.gmt_unix_time = time ( NULL );
- iob_populate ( &tls->rx_header_iobuf, &tls->rx_header, 0,
- sizeof ( tls->rx_header ) );
- INIT_LIST_HEAD ( &tls->rx_data );
- if ( ( rc = tls_generate_random ( tls, &tls->client_random.random,
- ( sizeof ( tls->client_random.random ) ) ) ) != 0 ) {
+ tls->client.random.gmt_unix_time = time ( NULL );
+ iob_populate ( &tls->rx.iobuf, &tls->rx.header, 0,
+ sizeof ( tls->rx.header ) );
+ INIT_LIST_HEAD ( &tls->rx.data );
+ if ( ( rc = tls_generate_random ( tls, &tls->client.random.random,
+ ( sizeof ( tls->client.random.random ) ) ) ) != 0 ) {
goto err_random;
}
if ( ( rc = tls_session ( tls, name ) ) != 0 )
diff --git a/src/net/validator.c b/src/net/validator.c
index 69c0df3..e1371d2 100644
--- a/src/net/validator.c
+++ b/src/net/validator.c
@@ -135,9 +135,11 @@ struct validator {
* @ret name Validator name
*/
static const char * validator_name ( struct validator *validator ) {
+ struct x509_certificate *cert;
- /* Use name of first certificate in chain */
- return x509_name ( x509_first ( validator->chain ) );
+ /* Use name of first certificate in chain, if present */
+ cert = x509_first ( validator->chain );
+ return ( cert ? x509_name ( cert ) : "<empty>" );
}
/**
diff --git a/src/tests/cms_test.c b/src/tests/cms_test.c
index f35fa20..fc4f6bd 100644
--- a/src/tests/cms_test.c
+++ b/src/tests/cms_test.c
@@ -36,30 +36,40 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <ipxe/sha256.h>
#include <ipxe/x509.h>
+#include <ipxe/image.h>
#include <ipxe/uaccess.h>
+#include <ipxe/der.h>
#include <ipxe/cms.h>
+#include <ipxe/privkey.h>
#include <ipxe/test.h>
/** Fingerprint algorithm used for X.509 test certificates */
#define cms_test_algorithm sha256_algorithm
-/** CMS test code blob */
-struct cms_test_code {
- /** Data */
- const void *data;
- /** Length of data */
- size_t len;
+/** Test image */
+struct cms_test_image {
+ /** Image */
+ struct image image;
+};
+
+/** Test CMS message */
+struct cms_test_message {
+ /** Message image */
+ struct image image;
+ /** Parsed message */
+ struct cms_message *cms;
};
-/** CMS test signature */
-struct cms_test_signature {
- /** Data */
+/** Test CMS key pair */
+struct cms_test_keypair {
+ /** Private key */
+ struct private_key privkey;
+ /** Certificate data */
const void *data;
- /** Length of data */
+ /** Length of certificate data */
size_t len;
-
- /** Parsed signature */
- struct cms_signature *sig;
+ /** Parsed certificate */
+ struct x509_certificate *cert;
};
/** Define inline data */
@@ -68,24 +78,49 @@ struct cms_test_signature {
/** Define inline fingerprint data */
#define FINGERPRINT(...) { __VA_ARGS__ }
-/** Define a test code blob */
-#define SIGNED_CODE( name, DATA ) \
- static const uint8_t name ## _data[] = DATA; \
- static struct cms_test_code name = { \
- .data = name ## _data, \
- .len = sizeof ( name ## _data ), \
+/** Define a test image */
+#define IMAGE( NAME, DATA ) \
+ static uint8_t NAME ## _data[] = DATA; \
+ static struct cms_test_image NAME = { \
+ .image = { \
+ .refcnt = REF_INIT ( ref_no_free ), \
+ .name = #NAME, \
+ .data = ( userptr_t ) ( NAME ## _data ), \
+ .len = sizeof ( NAME ## _data ), \
+ }, \
+ }
+
+/** Define a test message */
+#define MESSAGE( NAME, DATA ) \
+ static const uint8_t NAME ## _data[] = DATA; \
+ static struct cms_test_message NAME = { \
+ .image = { \
+ .refcnt = REF_INIT ( ref_no_free ), \
+ .name = #NAME, \
+ .type = &der_image_type, \
+ .data = ( userptr_t ) ( NAME ## _data ), \
+ .len = sizeof ( NAME ## _data ), \
+ }, \
}
-/** Define a test signature */
-#define SIGNATURE( name, DATA ) \
- static const uint8_t name ## _data[] = DATA; \
- static struct cms_test_signature name = { \
- .data = name ## _data, \
- .len = sizeof ( name ## _data ), \
+/** Define a test key pair */
+#define KEYPAIR( NAME, PRIVKEY, CERT ) \
+ static uint8_t NAME ## _privkey[] = PRIVKEY; \
+ static const uint8_t NAME ## _cert[] = CERT; \
+ static struct cms_test_keypair NAME = { \
+ .privkey = { \
+ .refcnt = REF_INIT ( ref_no_free ), \
+ .builder = { \
+ .data = NAME ## _privkey, \
+ .len = sizeof ( NAME ## _privkey ), \
+ }, \
+ }, \
+ .data = NAME ## _cert, \
+ .len = sizeof ( NAME ## _cert ), \
}
/** Code that has been signed */
-SIGNED_CODE ( test_code,
+IMAGE ( test_code,
DATA ( 0x23, 0x21, 0x69, 0x70, 0x78, 0x65, 0x0a, 0x0a, 0x65, 0x63,
0x68, 0x6f, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
0x20, 0x61, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20,
@@ -97,7 +132,7 @@ SIGNED_CODE ( test_code,
0x65, 0x6c, 0x6c, 0x0a ) );
/** Code that has not been signed */
-SIGNED_CODE ( bad_code,
+IMAGE ( bad_code,
DATA ( 0x23, 0x21, 0x69, 0x70, 0x78, 0x65, 0x0a, 0x0a, 0x65, 0x63,
0x68, 0x6f, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
0x20, 0x61, 0x20, 0x6d, 0x61, 0x6c, 0x69, 0x63, 0x69, 0x6f,
@@ -107,8 +142,125 @@ SIGNED_CODE ( bad_code,
0x6f, 0x75, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x21, 0x0a, 0x73,
0x68, 0x65, 0x6c, 0x6c, 0x0a ) );
+/** Plaintext of encrypted code */
+IMAGE ( hidden_code,
+ DATA ( 0x23, 0x21, 0x69, 0x70, 0x78, 0x65, 0x0a, 0x0a, 0x65, 0x63,
+ 0x68, 0x6f, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74,
+ 0x65, 0x64, 0x20, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x2e, 0x20, 0x20, 0x44, 0x6f, 0x20,
+ 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x21, 0x0a, 0x73,
+ 0x68, 0x65, 0x6c, 0x6c, 0x0a ) );
+
+/** Code encrypted with AES-256-CBC */
+IMAGE ( hidden_code_cbc_dat,
+ DATA ( 0xaa, 0x63, 0x9f, 0x12, 0xeb, 0x1e, 0xdd, 0x9b, 0xb6, 0x4d,
+ 0x81, 0xd5, 0xba, 0x2d, 0x86, 0x7a, 0x1c, 0x39, 0x10, 0x60,
+ 0x43, 0xac, 0x1b, 0x4e, 0x43, 0xb7, 0x50, 0x5a, 0x6d, 0x7a,
+ 0x4b, 0xd8, 0x65, 0x3c, 0x3e, 0xbd, 0x40, 0x9e, 0xb2, 0xe1,
+ 0x7d, 0x80, 0xf8, 0x22, 0x50, 0xf7, 0x32, 0x3a, 0x43, 0xf9,
+ 0xdf, 0xa6, 0xab, 0xa4, 0xb3, 0xdd, 0x27, 0x88, 0xd9, 0xb0,
+ 0x99, 0xb5, 0x7a, 0x89, 0x6c, 0xb7, 0x63, 0x45, 0x42, 0x7d,
+ 0xbe, 0x43, 0xab, 0x7e, 0x6c, 0x0c, 0xd5, 0xba, 0x9e, 0x37 ) );
+
+/** Envelope for code encrypted with AES-256-CBC */
+MESSAGE ( hidden_code_cbc_env,
+ DATA ( 0x30, 0x82, 0x01, 0x70, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x82, 0x01, 0x61, 0x30,
+ 0x82, 0x01, 0x5d, 0x02, 0x01, 0x00, 0x31, 0x82, 0x01, 0x2a,
+ 0x30, 0x82, 0x01, 0x26, 0x02, 0x01, 0x00, 0x30, 0x81, 0x8e,
+ 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d,
+ 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72,
+ 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70,
+ 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58,
+ 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73,
+ 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x02,
+ 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x81, 0x80,
+ 0x10, 0x26, 0x94, 0x97, 0xe5, 0x84, 0x53, 0xf9, 0x03, 0xc4,
+ 0xf6, 0xc1, 0x55, 0xf5, 0x00, 0x23, 0xb9, 0x80, 0x20, 0x85,
+ 0xd2, 0xf2, 0xc4, 0x61, 0xdb, 0x73, 0x8d, 0xe1, 0xa1, 0x73,
+ 0x7d, 0x31, 0x12, 0xb7, 0xac, 0xa4, 0xe0, 0x40, 0x10, 0xcf,
+ 0xd5, 0x55, 0x70, 0x75, 0x9f, 0x7b, 0x61, 0xd3, 0x9e, 0xc6,
+ 0x58, 0x78, 0x05, 0x66, 0xc1, 0x86, 0x2f, 0x00, 0xcd, 0xe9,
+ 0x32, 0x63, 0x7c, 0x95, 0xd7, 0x75, 0x46, 0xde, 0x76, 0x7d,
+ 0x49, 0x64, 0x86, 0xd6, 0xeb, 0x0f, 0x1c, 0x01, 0x20, 0xb9,
+ 0xb9, 0x42, 0xc4, 0x20, 0x1f, 0x3f, 0xae, 0x5f, 0xb9, 0xd0,
+ 0xb6, 0x49, 0xcc, 0x4c, 0xd9, 0xcb, 0x36, 0xa4, 0x2f, 0xb1,
+ 0x97, 0x40, 0xf3, 0xe7, 0x19, 0x88, 0x93, 0x58, 0x61, 0x31,
+ 0xac, 0x9a, 0x93, 0x6e, 0x79, 0x31, 0x3a, 0x79, 0xa4, 0x20,
+ 0x38, 0x17, 0x92, 0x40, 0x7c, 0x98, 0xea, 0x86, 0x30, 0x2a,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+ 0x01, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+ 0x03, 0x04, 0x01, 0x2a, 0x04, 0x10, 0xd8, 0x80, 0xc5, 0xfa,
+ 0xc3, 0x25, 0xa0, 0x22, 0xb5, 0x6c, 0x0c, 0x27, 0x2c, 0xe9,
+ 0xba, 0xcf ) );
+
+/** Code encrypted with AES-256-GCM (no block padding) */
+IMAGE ( hidden_code_gcm_dat,
+ DATA ( 0x0c, 0x96, 0xa6, 0x54, 0x9a, 0xc2, 0x24, 0x89, 0x15, 0x00,
+ 0x90, 0xe1, 0x35, 0xca, 0x4a, 0x84, 0x8e, 0x0b, 0xc3, 0x5e,
+ 0xc0, 0x61, 0x61, 0xbd, 0x2e, 0x69, 0x84, 0x7a, 0x2f, 0xf6,
+ 0xbe, 0x39, 0x04, 0x0a, 0x8d, 0x91, 0x6b, 0xaf, 0x63, 0xd4,
+ 0x03, 0xf1, 0x72, 0x38, 0xee, 0x27, 0xd6, 0x5a, 0xae, 0x15,
+ 0xd5, 0xec, 0xb6, 0xb6, 0x4f, 0x6f, 0xf6, 0x76, 0x22, 0x74,
+ 0xca, 0x72, 0x0b, 0xfa, 0x6a, 0x0e, 0x4a, 0x3e, 0x8c, 0x60,
+ 0x78, 0x24, 0x48, 0x58, 0xdd ) );
+
+/** Envelope for code encrypted with AES-256-GCM (no block padding) */
+MESSAGE ( hidden_code_gcm_env,
+ DATA ( 0x30, 0x82, 0x01, 0x85, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x17, 0xa0, 0x82, 0x01,
+ 0x74, 0x30, 0x82, 0x01, 0x70, 0x02, 0x01, 0x00, 0x31, 0x82,
+ 0x01, 0x2a, 0x30, 0x82, 0x01, 0x26, 0x02, 0x01, 0x00, 0x30,
+ 0x81, 0x8e, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17,
+ 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68,
+ 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+ 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08,
+ 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f,
+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69,
+ 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74,
+ 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43,
+ 0x41, 0x02, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04,
+ 0x81, 0x80, 0x7e, 0xbc, 0xba, 0xee, 0xfa, 0x50, 0x46, 0xee,
+ 0xed, 0xf1, 0x54, 0xe1, 0x46, 0xeb, 0x57, 0x3e, 0x76, 0xd7,
+ 0x8f, 0xe3, 0x26, 0x42, 0x3d, 0x28, 0xf9, 0xdc, 0x20, 0xe6,
+ 0x27, 0x3b, 0x89, 0xcb, 0xab, 0xd5, 0xad, 0xc2, 0xf0, 0x4f,
+ 0xa8, 0xb9, 0x77, 0x5b, 0x6c, 0xe6, 0x34, 0x22, 0x73, 0x5b,
+ 0xa4, 0x8e, 0x1c, 0xc2, 0xf8, 0x50, 0xef, 0xe5, 0xcf, 0x80,
+ 0x16, 0x79, 0x6b, 0x0f, 0xa7, 0xfd, 0xdc, 0x60, 0x9c, 0x94,
+ 0x60, 0xa6, 0x12, 0x5a, 0xfb, 0xc2, 0xc8, 0x4c, 0x64, 0x83,
+ 0x99, 0x73, 0xfc, 0xa1, 0xf8, 0xa5, 0x82, 0x75, 0xba, 0x53,
+ 0xeb, 0xc8, 0x94, 0x0e, 0x29, 0x23, 0x9a, 0x2b, 0xa6, 0x63,
+ 0x2d, 0x5b, 0x9f, 0x38, 0x70, 0x21, 0xe8, 0xe9, 0xa6, 0xcf,
+ 0xf2, 0xbe, 0x66, 0xf4, 0xcc, 0x91, 0x01, 0x4f, 0x04, 0x00,
+ 0x4a, 0x55, 0xc9, 0x42, 0x76, 0xd4, 0x3f, 0x65, 0x0c, 0x76,
+ 0x30, 0x2b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x01, 0x30, 0x1e, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x01, 0x2e, 0x30, 0x11, 0x04, 0x0c,
+ 0x72, 0xb5, 0x14, 0xfb, 0x05, 0x78, 0x70, 0x1c, 0xf4, 0x4b,
+ 0xba, 0xbf, 0x02, 0x01, 0x10, 0x04, 0x10, 0x1e, 0x44, 0xda,
+ 0x5c, 0x75, 0x7e, 0x4f, 0xa7, 0xe7, 0xd9, 0x98, 0x80, 0x9c,
+ 0x25, 0x6a, 0xfb ) );
+
/** Valid signature */
-SIGNATURE ( codesigned_sig,
+MESSAGE ( codesigned_sig,
DATA ( 0x30, 0x82, 0x0c, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x0c, 0x32, 0x30,
0x82, 0x0c, 0x2e, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07,
@@ -426,7 +578,7 @@ SIGNATURE ( codesigned_sig,
0xbf ) );
/** Signature with a broken certificate chain */
-SIGNATURE ( brokenchain_sig,
+MESSAGE ( brokenchain_sig,
DATA ( 0x30, 0x82, 0x09, 0x8a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x09, 0x7b, 0x30,
0x82, 0x09, 0x77, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07,
@@ -674,7 +826,7 @@ SIGNATURE ( brokenchain_sig,
0xf9, 0x71, 0x64, 0x03, 0x05, 0xbf ) );
/** Signature generated with a non-code-signing certificate */
-SIGNATURE ( genericsigned_sig,
+MESSAGE ( genericsigned_sig,
DATA ( 0x30, 0x82, 0x0c, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x0c, 0x20, 0x30,
0x82, 0x0c, 0x1c, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07,
@@ -990,7 +1142,7 @@ SIGNATURE ( genericsigned_sig,
0x7e, 0x7c, 0x99 ) );
/** Signature generated with a non-signing certificate */
-SIGNATURE ( nonsigned_sig,
+MESSAGE ( nonsigned_sig,
DATA ( 0x30, 0x82, 0x0c, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x0c, 0x03, 0x30,
0x82, 0x0b, 0xff, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07,
@@ -1302,6 +1454,138 @@ SIGNATURE ( nonsigned_sig,
0x5d, 0x70, 0x47, 0x54, 0xbc, 0x15, 0xad, 0x9c, 0xe8, 0x90,
0x52, 0x3e, 0x49, 0x86 ) );
+/** Client certificate and private key */
+KEYPAIR ( client_keypair,
+ DATA ( 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x04, 0x82, 0x02, 0x61, 0x30, 0x82, 0x02, 0x5d,
+ 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xb7, 0x9f, 0xb5,
+ 0x90, 0xfa, 0x47, 0x25, 0xee, 0x3b, 0x04, 0x02, 0x4f, 0xd4,
+ 0x1d, 0x62, 0x46, 0x9d, 0xce, 0x79, 0x3a, 0x80, 0x3a, 0xc4,
+ 0x06, 0x6a, 0x67, 0xd4, 0x3a, 0x61, 0x71, 0xcd, 0xb3, 0xcc,
+ 0x1b, 0xfc, 0x2f, 0x17, 0xa8, 0xf2, 0x26, 0x9e, 0x54, 0xd3,
+ 0x49, 0x81, 0x22, 0xa9, 0x72, 0x4c, 0xe8, 0x92, 0xb7, 0x1e,
+ 0x44, 0x8f, 0xa9, 0x4d, 0x83, 0x0b, 0x89, 0x2a, 0xc7, 0xb3,
+ 0xad, 0x54, 0x32, 0x76, 0x62, 0x1e, 0xe5, 0xbe, 0xc1, 0xa8,
+ 0x7a, 0x2b, 0xf0, 0xa9, 0x9a, 0xfb, 0xb8, 0x18, 0x0c, 0x30,
+ 0x5a, 0x13, 0x9c, 0x21, 0x26, 0x96, 0x4f, 0x39, 0x98, 0x64,
+ 0x41, 0x3b, 0x94, 0xc8, 0xe3, 0xb7, 0x8c, 0x33, 0x9e, 0xd0,
+ 0x71, 0xd0, 0x2f, 0xe3, 0x7d, 0x2c, 0x57, 0x27, 0x42, 0x26,
+ 0xd9, 0x2c, 0xb4, 0x55, 0xd5, 0x66, 0xb7, 0xbf, 0x00, 0xa1,
+ 0xcc, 0x61, 0x19, 0x99, 0x61, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0x02, 0x81, 0x80, 0x50, 0x63, 0x2f, 0xe6, 0xb7, 0x5a, 0xfc,
+ 0x85, 0x0d, 0xfb, 0x14, 0x54, 0x04, 0x65, 0x94, 0xc7, 0x9b,
+ 0x80, 0x6f, 0xdc, 0x27, 0x95, 0x12, 0x8a, 0x48, 0x7d, 0x0a,
+ 0x11, 0x40, 0xe5, 0xc4, 0x8b, 0x29, 0x19, 0x3b, 0x4f, 0x16,
+ 0x89, 0x94, 0xf1, 0x49, 0x31, 0x93, 0x8a, 0x43, 0x69, 0x7c,
+ 0x4b, 0x18, 0xd6, 0x5c, 0x9c, 0xa4, 0x38, 0x99, 0xb8, 0x21,
+ 0xc1, 0xf4, 0x03, 0xe9, 0xe1, 0xa1, 0x8b, 0xcb, 0x51, 0x4f,
+ 0x64, 0x68, 0x1c, 0x73, 0xc0, 0x0d, 0xd2, 0xcd, 0x87, 0xcc,
+ 0x45, 0xe8, 0xbf, 0x88, 0xea, 0x6c, 0x42, 0xfa, 0x03, 0x7a,
+ 0x29, 0xd2, 0xcf, 0xf1, 0xcb, 0xae, 0xea, 0xfb, 0x50, 0xf2,
+ 0xbd, 0x02, 0x4f, 0x2f, 0x4f, 0xba, 0x82, 0xa9, 0xde, 0x60,
+ 0x56, 0xd4, 0x07, 0x73, 0xdf, 0x12, 0x09, 0x73, 0x7b, 0x54,
+ 0x35, 0xc6, 0x28, 0x10, 0xb0, 0xbd, 0xc8, 0xe1, 0x8f, 0xb2,
+ 0x41, 0x02, 0x41, 0x00, 0xd8, 0xf9, 0x6c, 0x70, 0x56, 0x3c,
+ 0x74, 0x44, 0x53, 0x13, 0xed, 0x92, 0xab, 0xbc, 0x0c, 0x5c,
+ 0x66, 0x2c, 0xd7, 0xed, 0x10, 0x82, 0xe3, 0xe3, 0x2e, 0xda,
+ 0x4d, 0x3e, 0x1f, 0xc0, 0x50, 0xa8, 0xf2, 0xce, 0x77, 0xa9,
+ 0xae, 0xa2, 0x2d, 0x49, 0x6a, 0x6f, 0x01, 0xe3, 0xca, 0x57,
+ 0xf4, 0xcc, 0xb4, 0x3f, 0xd9, 0xc3, 0x58, 0x54, 0xe7, 0x62,
+ 0xfc, 0x40, 0xc8, 0xba, 0x18, 0x0d, 0xfe, 0x89, 0x02, 0x41,
+ 0x00, 0xd8, 0xa6, 0xaa, 0x4b, 0xcc, 0xcf, 0xc4, 0x47, 0x84,
+ 0x13, 0x39, 0x5b, 0x2e, 0xcb, 0xe0, 0x41, 0xd0, 0x2c, 0x96,
+ 0x58, 0x73, 0xab, 0xf6, 0x41, 0x0c, 0x7b, 0xbe, 0x60, 0xa1,
+ 0xcb, 0x00, 0x1a, 0xb0, 0x4b, 0xc1, 0xf5, 0x27, 0x43, 0x97,
+ 0x87, 0x30, 0x3c, 0x27, 0xa3, 0xe3, 0xf1, 0xa7, 0x45, 0x01,
+ 0xe2, 0x1c, 0x43, 0xe9, 0x48, 0x43, 0x76, 0x24, 0x4b, 0x2b,
+ 0xc7, 0x67, 0x3e, 0x4e, 0x19, 0x02, 0x40, 0x6a, 0x43, 0x96,
+ 0x31, 0x5a, 0x7a, 0xd7, 0x32, 0x93, 0x41, 0xa2, 0x4c, 0x00,
+ 0x21, 0xe4, 0x27, 0xe8, 0xbe, 0xb3, 0xad, 0xde, 0x35, 0x4c,
+ 0xa8, 0xfa, 0x4c, 0x5e, 0x22, 0x3b, 0xe8, 0xb3, 0x58, 0x5b,
+ 0x3a, 0x75, 0x6e, 0xbc, 0x21, 0x9f, 0x6e, 0x62, 0x5b, 0x25,
+ 0xa0, 0xcb, 0x7b, 0xd2, 0x5f, 0xe3, 0x33, 0x96, 0x52, 0x4e,
+ 0xd3, 0x9e, 0x53, 0x63, 0x59, 0xd3, 0x35, 0x19, 0x0c, 0xd9,
+ 0x89, 0x02, 0x41, 0x00, 0x8f, 0x8d, 0xb7, 0xaf, 0x6c, 0x31,
+ 0x8b, 0x0c, 0x1c, 0x1e, 0xa4, 0xd5, 0x9f, 0x67, 0x65, 0xdc,
+ 0x15, 0xf5, 0x45, 0x55, 0xac, 0xa7, 0x98, 0x0f, 0x38, 0x17,
+ 0x52, 0x69, 0x33, 0x2b, 0x90, 0x91, 0x1e, 0x99, 0xc4, 0x16,
+ 0x0e, 0x03, 0x42, 0x87, 0x48, 0x55, 0xc3, 0xaa, 0x5b, 0xe2,
+ 0x86, 0x84, 0x3a, 0x20, 0x39, 0xbc, 0x61, 0xfa, 0x09, 0x01,
+ 0x62, 0x41, 0x10, 0xec, 0x1a, 0xa3, 0xf5, 0x19, 0x02, 0x41,
+ 0x00, 0x98, 0x04, 0xc8, 0x8e, 0xd0, 0xfa, 0xe5, 0xab, 0x8a,
+ 0x1c, 0x4a, 0xc2, 0xf7, 0xd4, 0xad, 0x52, 0x51, 0x81, 0xa6,
+ 0x59, 0x62, 0x84, 0x16, 0x82, 0xf2, 0x5d, 0xd0, 0x5d, 0x4a,
+ 0xcf, 0x94, 0x2f, 0x13, 0x47, 0xd4, 0xc2, 0x7f, 0x89, 0x2e,
+ 0x40, 0xf5, 0xfc, 0xf8, 0x82, 0xc6, 0x53, 0xd4, 0x75, 0x32,
+ 0x47, 0x1d, 0xcf, 0xd1, 0xae, 0x35, 0x41, 0x7a, 0xdc, 0x10,
+ 0x0c, 0xc2, 0xd6, 0xe1, 0xd5 ),
+ DATA ( 0x30, 0x82, 0x02, 0x7f, 0x30, 0x82, 0x01, 0xe8, 0x02, 0x01,
+ 0x08, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64,
+ 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65,
+ 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65,
+ 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x32,
+ 0x34, 0x30, 0x38, 0x32, 0x39, 0x32, 0x32, 0x31, 0x39, 0x35,
+ 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x35, 0x30, 0x38, 0x32, 0x39,
+ 0x32, 0x32, 0x31, 0x39, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x86,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12,
+ 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43,
+ 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18,
+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46,
+ 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73,
+ 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e,
+ 0x6f, 0x72, 0x67, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x14, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65,
+ 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
+ 0x81, 0x81, 0x00, 0xb7, 0x9f, 0xb5, 0x90, 0xfa, 0x47, 0x25,
+ 0xee, 0x3b, 0x04, 0x02, 0x4f, 0xd4, 0x1d, 0x62, 0x46, 0x9d,
+ 0xce, 0x79, 0x3a, 0x80, 0x3a, 0xc4, 0x06, 0x6a, 0x67, 0xd4,
+ 0x3a, 0x61, 0x71, 0xcd, 0xb3, 0xcc, 0x1b, 0xfc, 0x2f, 0x17,
+ 0xa8, 0xf2, 0x26, 0x9e, 0x54, 0xd3, 0x49, 0x81, 0x22, 0xa9,
+ 0x72, 0x4c, 0xe8, 0x92, 0xb7, 0x1e, 0x44, 0x8f, 0xa9, 0x4d,
+ 0x83, 0x0b, 0x89, 0x2a, 0xc7, 0xb3, 0xad, 0x54, 0x32, 0x76,
+ 0x62, 0x1e, 0xe5, 0xbe, 0xc1, 0xa8, 0x7a, 0x2b, 0xf0, 0xa9,
+ 0x9a, 0xfb, 0xb8, 0x18, 0x0c, 0x30, 0x5a, 0x13, 0x9c, 0x21,
+ 0x26, 0x96, 0x4f, 0x39, 0x98, 0x64, 0x41, 0x3b, 0x94, 0xc8,
+ 0xe3, 0xb7, 0x8c, 0x33, 0x9e, 0xd0, 0x71, 0xd0, 0x2f, 0xe3,
+ 0x7d, 0x2c, 0x57, 0x27, 0x42, 0x26, 0xd9, 0x2c, 0xb4, 0x55,
+ 0xd5, 0x66, 0xb7, 0xbf, 0x00, 0xa1, 0xcc, 0x61, 0x19, 0x99,
+ 0x61, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
+ 0x00, 0x03, 0x81, 0x81, 0x00, 0x22, 0x6e, 0x8b, 0x81, 0xc3,
+ 0x13, 0x89, 0x31, 0xcc, 0x6d, 0x44, 0xa5, 0x77, 0x31, 0x79,
+ 0xff, 0xea, 0x8a, 0x4e, 0xe6, 0xb6, 0x4a, 0xf0, 0x01, 0xd3,
+ 0x9f, 0xd7, 0x23, 0x14, 0x4c, 0xdd, 0xa3, 0xdf, 0xd6, 0x2b,
+ 0x2a, 0xc4, 0xba, 0xf7, 0xef, 0xfd, 0x78, 0xd5, 0xd7, 0xfd,
+ 0xd7, 0x77, 0x17, 0x20, 0x4f, 0xf3, 0x94, 0xd6, 0x74, 0xd5,
+ 0x09, 0x54, 0x16, 0x49, 0x6e, 0xd9, 0x41, 0xa7, 0x43, 0x77,
+ 0x7f, 0xef, 0xd3, 0xd7, 0xbb, 0x8b, 0xf0, 0x7d, 0x1f, 0x00,
+ 0x4a, 0xac, 0x18, 0xff, 0x20, 0x32, 0xd1, 0x1c, 0x13, 0xf2,
+ 0xe0, 0xd7, 0x70, 0xec, 0xb6, 0xf7, 0xa3, 0x42, 0xa1, 0x64,
+ 0x26, 0x30, 0x9f, 0x47, 0xd4, 0xfb, 0xfb, 0x06, 0xdb, 0x0b,
+ 0xb3, 0x27, 0xe6, 0x04, 0xe2, 0x94, 0x35, 0x8b, 0xa5, 0xfd,
+ 0x80, 0x1d, 0xa6, 0x72, 0x32, 0x30, 0x99, 0x6c, 0xbf, 0xd3,
+ 0x26, 0xa3, 0x8a ) );
+
/** iPXE self-test root CA certificate */
static uint8_t root_crt_fingerprint[] =
FINGERPRINT ( 0x71, 0x5d, 0x51, 0x37, 0x5e, 0x18, 0xb3, 0xbc,
@@ -1345,26 +1629,55 @@ static time_t test_time = 1332374737ULL; /* Thu Mar 22 00:05:37 2012 */
static time_t test_expired = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */
/**
- * Report signature parsing test result
+ * Report message parsing test result
*
- * @v sgn Test signature
+ * @v msg Test message
* @v file Test code file
* @v line Test code line
*/
-static void cms_signature_okx ( struct cms_test_signature *sgn,
- const char *file, unsigned int line ) {
+static void cms_message_okx ( struct cms_test_message *msg,
+ const char *file, unsigned int line ) {
+ const void *data = ( ( void * ) msg->image.data );
- okx ( cms_signature ( sgn->data, sgn->len, &sgn->sig ) == 0,
+ /* Fix up image data pointer */
+ msg->image.data = virt_to_user ( data );
+
+ /* Check ability to parse message */
+ okx ( cms_message ( &msg->image, &msg->cms ) == 0, file, line );
+
+ /* Reset image data pointer */
+ msg->image.data = ( ( userptr_t ) data );
+}
+#define cms_message_ok( msg ) \
+ cms_message_okx ( msg, __FILE__, __LINE__ )
+
+/**
+ * Report key pair parsing test result
+ *
+ * @v keypair Test key pair
+ * @v file Test code file
+ * @v line Test code line
+ */
+static void cms_keypair_okx ( struct cms_test_keypair *keypair,
+ const char *file, unsigned int line ) {
+
+ /* Check ability to parse certificate */
+ okx ( x509_certificate ( keypair->data, keypair->len,
+ &keypair->cert ) == 0, file, line );
+ okx ( keypair->cert != NULL, file, line );
+
+ /* Check certificate can be identified by public key */
+ okx ( x509_find_key ( NULL, &keypair->privkey ) == keypair->cert,
file, line );
}
-#define cms_signature_ok( sgn ) \
- cms_signature_okx ( sgn, __FILE__, __LINE__ )
+#define cms_keypair_ok( keypair ) \
+ cms_keypair_okx ( keypair, __FILE__, __LINE__ )
/**
* Report signature verification test result
*
- * @v sgn Test signature
- * @v code Test signed code
+ * @v msg Test signature message
+ * @v img Test signed image
* @v name Test verification name
* @v time Test verification time
* @v store Test certificate store
@@ -1372,25 +1685,36 @@ static void cms_signature_okx ( struct cms_test_signature *sgn,
* @v file Test code file
* @v line Test code line
*/
-static void cms_verify_okx ( struct cms_test_signature *sgn,
- struct cms_test_code *code, const char *name,
+static void cms_verify_okx ( struct cms_test_message *msg,
+ struct cms_test_image *img, const char *name,
time_t time, struct x509_chain *store,
struct x509_root *root, const char *file,
unsigned int line ) {
+ const void *data = ( ( void * ) img->image.data );
+
+ /* Fix up image data pointer */
+ img->image.data = virt_to_user ( data );
+
+ /* Invalidate any certificates from previous tests */
+ x509_invalidate_chain ( msg->cms->certificates );
- x509_invalidate_chain ( sgn->sig->certificates );
- okx ( cms_verify ( sgn->sig, virt_to_user ( code->data ), code->len,
- name, time, store, root ) == 0, file, line );
+ /* Check ability to verify signature */
+ okx ( cms_verify ( msg->cms, &img->image, name, time, store,
+ root ) == 0, file, line );
+ okx ( img->image.flags & IMAGE_TRUSTED, file, line );
+
+ /* Reset image data pointer */
+ img->image.data = ( ( userptr_t ) data );
}
-#define cms_verify_ok( sgn, code, name, time, store, root ) \
- cms_verify_okx ( sgn, code, name, time, store, root, \
+#define cms_verify_ok( msg, img, name, time, store, root ) \
+ cms_verify_okx ( msg, img, name, time, store, root, \
__FILE__, __LINE__ )
/**
* Report signature verification failure test result
*
- * @v sgn Test signature
- * @v code Test signed code
+ * @v msg Test signature message
+ * @v img Test signed image
* @v name Test verification name
* @v time Test verification time
* @v store Test certificate store
@@ -1398,31 +1722,80 @@ static void cms_verify_okx ( struct cms_test_signature *sgn,
* @v file Test code file
* @v line Test code line
*/
-static void cms_verify_fail_okx ( struct cms_test_signature *sgn,
- struct cms_test_code *code, const char *name,
+static void cms_verify_fail_okx ( struct cms_test_message *msg,
+ struct cms_test_image *img, const char *name,
time_t time, struct x509_chain *store,
struct x509_root *root, const char *file,
unsigned int line ) {
+ const void *data = ( ( void * ) img->image.data );
+
+ /* Fix up image data pointer */
+ img->image.data = virt_to_user ( data );
+
+ /* Invalidate any certificates from previous tests */
+ x509_invalidate_chain ( msg->cms->certificates );
- x509_invalidate_chain ( sgn->sig->certificates );
- okx ( cms_verify ( sgn->sig, virt_to_user ( code->data ), code->len,
- name, time, store, root ) != 0, file, line );
+ /* Check inability to verify signature */
+ okx ( cms_verify ( msg->cms, &img->image, name, time, store,
+ root ) != 0, file, line );
+ okx ( ! ( img->image.flags & IMAGE_TRUSTED ), file, line );
+
+ /* Reset image data pointer */
+ img->image.data = ( ( userptr_t ) data );
}
-#define cms_verify_fail_ok( sgn, code, name, time, store, root ) \
- cms_verify_fail_okx ( sgn, code, name, time, store, root, \
+#define cms_verify_fail_ok( msg, img, name, time, store, root ) \
+ cms_verify_fail_okx ( msg, img, name, time, store, root, \
__FILE__, __LINE__ )
/**
+ * Report decryption test result
+ *
+ * @v img Encrypted data image
+ * @v envelope Envelope message
+ * @v keypair Key pair
+ * @v expected Expected plaintext image
+ * @v file Test code file
+ * @v line Test code line
+ */
+static void cms_decrypt_okx ( struct cms_test_image *img,
+ struct cms_test_message *envelope,
+ struct cms_test_keypair *keypair,
+ struct cms_test_image *expected,
+ const char *file, unsigned int line ) {
+ const void *data = ( ( void * ) img->image.data );
+
+ /* Fix up image data pointer */
+ img->image.data = virt_to_user ( data );
+
+ /* Check ability to decrypt image */
+ okx ( cms_decrypt ( envelope->cms, &img->image, NULL,
+ &keypair->privkey ) == 0, file, line );
+
+ /* Check decrypted image matches expected plaintext */
+ okx ( img->image.len == expected->image.len, file, line );
+ okx ( memcmp_user ( img->image.data, 0, expected->image.data, 0,
+ expected->image.len ) == 0, file, line );
+}
+#define cms_decrypt_ok( data, envelope, keypair, expected ) \
+ cms_decrypt_okx ( data, envelope, keypair, expected, \
+ __FILE__, __LINE__ )
+
+/**
* Perform CMS self-tests
*
*/
static void cms_test_exec ( void ) {
- /* Check that all signatures can be parsed */
- cms_signature_ok ( &codesigned_sig );
- cms_signature_ok ( &brokenchain_sig );
- cms_signature_ok ( &genericsigned_sig );
- cms_signature_ok ( &nonsigned_sig );
+ /* Check that all key pairs can be parsed */
+ cms_keypair_ok ( &client_keypair );
+
+ /* Check that all messages can be parsed */
+ cms_message_ok ( &codesigned_sig );
+ cms_message_ok ( &brokenchain_sig );
+ cms_message_ok ( &genericsigned_sig );
+ cms_message_ok ( &nonsigned_sig );
+ cms_message_ok ( &hidden_code_cbc_env );
+ cms_message_ok ( &hidden_code_gcm_env );
/* Check good signature */
cms_verify_ok ( &codesigned_sig, &test_code, "codesign.test.ipxe.org",
@@ -1459,14 +1832,27 @@ static void cms_test_exec ( void ) {
cms_verify_fail_ok ( &codesigned_sig, &test_code,
NULL, test_expired, &empty_store, &test_root );
+ /* Check CBC decryption (with padding) */
+ cms_decrypt_ok ( &hidden_code_cbc_dat, &hidden_code_cbc_env,
+ &client_keypair, &hidden_code );
+
+ /* Check GCM decryption (no padding) */
+ cms_decrypt_ok ( &hidden_code_gcm_dat, &hidden_code_gcm_env,
+ &client_keypair, &hidden_code );
+
/* Sanity check */
assert ( list_empty ( &empty_store.links ) );
- /* Drop signature references */
- cms_put ( nonsigned_sig.sig );
- cms_put ( genericsigned_sig.sig );
- cms_put ( brokenchain_sig.sig );
- cms_put ( codesigned_sig.sig );
+ /* Drop message references */
+ cms_put ( hidden_code_gcm_env.cms );
+ cms_put ( hidden_code_cbc_env.cms );
+ cms_put ( nonsigned_sig.cms );
+ cms_put ( genericsigned_sig.cms );
+ cms_put ( brokenchain_sig.cms );
+ cms_put ( codesigned_sig.cms );
+
+ /* Drop certificate references */
+ x509_put ( client_keypair.cert );
}
/** CMS self-test */
diff --git a/src/tests/pubkey_test.c b/src/tests/pubkey_test.c
new file mode 100644
index 0000000..ff318bf
--- /dev/null
+++ b/src/tests/pubkey_test.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** @file
+ *
+ * Public key self-tests
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ipxe/crypto.h>
+#include <ipxe/test.h>
+#include "pubkey_test.h"
+
+/**
+ * Report public key encryption and decryption test result
+ *
+ * @v test Public key encryption and decryption test
+ * @v file Test code file
+ * @v line Test code line
+ */
+void pubkey_okx ( struct pubkey_test *test, const char *file,
+ unsigned int line ) {
+ struct pubkey_algorithm *pubkey = test->pubkey;
+ size_t max_len = pubkey_max_len ( pubkey, &test->private );
+ uint8_t encrypted[max_len];
+ uint8_t decrypted[max_len];
+ int encrypted_len;
+ int decrypted_len;
+
+ /* Test decrypting with private key to obtain known plaintext */
+ decrypted_len = pubkey_decrypt ( pubkey, &test->private,
+ test->ciphertext, test->ciphertext_len,
+ decrypted );
+ okx ( decrypted_len == ( ( int ) test->plaintext_len ), file, line );
+ okx ( memcmp ( decrypted, test->plaintext, test->plaintext_len ) == 0,
+ file, line );
+
+ /* Test encrypting with private key and decrypting with public key */
+ encrypted_len = pubkey_encrypt ( pubkey, &test->private,
+ test->plaintext, test->plaintext_len,
+ encrypted );
+ okx ( encrypted_len >= 0, file, line );
+ decrypted_len = pubkey_decrypt ( pubkey, &test->public, encrypted,
+ encrypted_len, decrypted );
+ okx ( decrypted_len == ( ( int ) test->plaintext_len ), file, line );
+ okx ( memcmp ( decrypted, test->plaintext, test->plaintext_len ) == 0,
+ file, line );
+
+ /* Test encrypting with public key and decrypting with private key */
+ encrypted_len = pubkey_encrypt ( pubkey, &test->public,
+ test->plaintext, test->plaintext_len,
+ encrypted );
+ okx ( encrypted_len >= 0, file, line );
+ decrypted_len = pubkey_decrypt ( pubkey, &test->private, encrypted,
+ encrypted_len, decrypted );
+ okx ( decrypted_len == ( ( int ) test->plaintext_len ), file, line );
+ okx ( memcmp ( decrypted, test->plaintext, test->plaintext_len ) == 0,
+ file, line );
+}
+
+/**
+ * Report public key signature test result
+ *
+ * @v test Public key signature test
+ * @v file Test code file
+ * @v line Test code line
+ */
+void pubkey_sign_okx ( struct pubkey_sign_test *test, const char *file,
+ unsigned int line ) {
+ struct pubkey_algorithm *pubkey = test->pubkey;
+ struct digest_algorithm *digest = test->digest;
+ size_t max_len = pubkey_max_len ( pubkey, &test->private );
+ uint8_t bad[test->signature_len];
+ uint8_t digestctx[digest->ctxsize ];
+ uint8_t digestout[digest->digestsize];
+ uint8_t signature[max_len];
+ int signature_len;
+
+ /* Construct digest over plaintext */
+ digest_init ( digest, digestctx );
+ digest_update ( digest, digestctx, test->plaintext,
+ test->plaintext_len );
+ digest_final ( digest, digestctx, digestout );
+
+ /* Test signing using private key */
+ signature_len = pubkey_sign ( pubkey, &test->private, digest,
+ digestout, signature );
+ okx ( signature_len == ( ( int ) test->signature_len ), file, line );
+ okx ( memcmp ( signature, test->signature, test->signature_len ) == 0,
+ file, line );
+
+ /* Test verification using public key */
+ okx ( pubkey_verify ( pubkey, &test->public, digest, digestout,
+ test->signature, test->signature_len ) == 0,
+ file, line );
+
+ /* Test verification failure of modified signature */
+ memcpy ( bad, test->signature, test->signature_len );
+ bad[ test->signature_len / 2 ] ^= 0x40;
+ okx ( pubkey_verify ( pubkey, &test->public, digest, digestout,
+ bad, sizeof ( bad ) ) != 0, file, line );
+}
diff --git a/src/tests/pubkey_test.h b/src/tests/pubkey_test.h
index cd65b87..20bb943 100644
--- a/src/tests/pubkey_test.h
+++ b/src/tests/pubkey_test.h
@@ -7,169 +7,151 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/crypto.h>
#include <ipxe/test.h>
-/**
- * Report public key decryption test result
- *
- * @v pubkey Public key algorithm
- * @v key Key
- * @v key_len Key length
- * @v ciphertext Ciphertext
- * @v ciphertext_len Ciphertext length
- * @v expected Expected plaintext
- * @v expected_len Expected plaintext length
- */
-#define pubkey_decrypt_ok( pubkey, key, key_len, ciphertext, \
- ciphertext_len, expected, expected_len ) do {\
- uint8_t ctx[ (pubkey)->ctxsize ]; \
- \
- ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \
- { \
- size_t max_len = pubkey_max_len ( (pubkey), ctx ); \
- uint8_t decrypted[ max_len ]; \
- int decrypted_len; \
- \
- decrypted_len = pubkey_decrypt ( (pubkey), ctx, \
- (ciphertext), \
- (ciphertext_len), \
- decrypted ); \
- ok ( decrypted_len == ( ( int ) (expected_len) ) ); \
- ok ( memcmp ( decrypted, (expected), \
- (expected_len) ) == 0 ); \
- } \
- pubkey_final ( (pubkey), ctx ); \
- } while ( 0 )
+/** A public-key encryption and decryption test */
+struct pubkey_test {
+ /** Public-key algorithm */
+ struct pubkey_algorithm *pubkey;
+ /** Private key */
+ const struct asn1_cursor private;
+ /** Public key */
+ const struct asn1_cursor public;
+ /** Plaintext */
+ const void *plaintext;
+ /** Length of plaintext */
+ size_t plaintext_len;
+ /** Ciphertext
+ *
+ * Note that the encryption process may include some random
+ * padding, so a given plaintext will encrypt to multiple
+ * different ciphertexts.
+ */
+ const void *ciphertext;
+ /** Length of ciphertext */
+ size_t ciphertext_len;
+};
+
+/** A public-key signature test */
+struct pubkey_sign_test {
+ /** Public-key algorithm */
+ struct pubkey_algorithm *pubkey;
+ /** Private key */
+ const struct asn1_cursor private;
+ /** Public key */
+ const struct asn1_cursor public;
+ /** Plaintext */
+ const void *plaintext;
+ /** Plaintext length */
+ size_t plaintext_len;
+ /** Signature algorithm */
+ struct digest_algorithm *digest;
+ /** Signature */
+ const void *signature;
+ /** Signature length */
+ size_t signature_len;
+};
+
+/** Define inline private key data */
+#define PRIVATE(...) { __VA_ARGS__ }
+
+/** Define inline public key data */
+#define PUBLIC(...) { __VA_ARGS__ }
+
+/** Define inline plaintext data */
+#define PLAINTEXT(...) { __VA_ARGS__ }
+
+/** Define inline ciphertext data */
+#define CIPHERTEXT(...) { __VA_ARGS__ }
+
+/** Define inline signature data */
+#define SIGNATURE(...) { __VA_ARGS__ }
/**
- * Report public key encryption and decryption test result
+ * Define a public-key encryption and decryption test
*
- * @v pubkey Public key algorithm
- * @v encrypt_key Encryption key
- * @v encrypt_key_len Encryption key length
- * @v decrypt_key Decryption key
- * @v decrypt_key_len Decryption key length
- * @v plaintext Plaintext
- * @v plaintext_len Plaintext length
+ * @v name Test name
+ * @v PUBKEY Public-key algorithm
+ * @v PRIVATE Private key
+ * @v PUBLIC Public key
+ * @v PLAINTEXT Plaintext
+ * @v CIPHERTEXT Ciphertext
+ * @ret test Encryption and decryption test
*/
-#define pubkey_encrypt_ok( pubkey, encrypt_key, encrypt_key_len, \
- decrypt_key, decrypt_key_len, plaintext, \
- plaintext_len ) do { \
- uint8_t ctx[ (pubkey)->ctxsize ]; \
- \
- ok ( pubkey_init ( (pubkey), ctx, (encrypt_key), \
- (encrypt_key_len) ) == 0 ); \
- { \
- size_t max_len = pubkey_max_len ( (pubkey), ctx ); \
- uint8_t encrypted[ max_len ]; \
- int encrypted_len; \
- \
- encrypted_len = pubkey_encrypt ( (pubkey), ctx, \
- (plaintext), \
- (plaintext_len), \
- encrypted ); \
- ok ( encrypted_len >= 0 ); \
- pubkey_decrypt_ok ( (pubkey), (decrypt_key), \
- (decrypt_key_len), encrypted, \
- encrypted_len, (plaintext), \
- (plaintext_len) ); \
- } \
- pubkey_final ( (pubkey), ctx ); \
- } while ( 0 )
+#define PUBKEY_TEST( name, PUBKEY, PRIVATE, PUBLIC, PLAINTEXT, \
+ CIPHERTEXT ) \
+ static const uint8_t name ## _private[] = PRIVATE; \
+ static const uint8_t name ## _public[] = PUBLIC; \
+ static const uint8_t name ## _plaintext[] = PLAINTEXT; \
+ static const uint8_t name ## _ciphertext[] = CIPHERTEXT; \
+ static struct pubkey_test name = { \
+ .pubkey = PUBKEY, \
+ .private = { \
+ .data = name ## _private, \
+ .len = sizeof ( name ## _private ), \
+ }, \
+ .public = { \
+ .data = name ## _public, \
+ .len = sizeof ( name ## _public ), \
+ }, \
+ .plaintext = name ## _plaintext, \
+ .plaintext_len = sizeof ( name ## _plaintext ), \
+ .ciphertext = name ## _ciphertext, \
+ .ciphertext_len = sizeof ( name ## _ciphertext ), \
+ }
/**
- * Report public key signature test result
+ * Define a public-key signature test
*
- * @v pubkey Public key algorithm
- * @v key Key
- * @v key_len Key length
- * @v digest Digest algorithm
- * @v plaintext Plaintext
- * @v plaintext_len Plaintext length
- * @v expected Expected signature
- * @v expected_len Expected signature length
+ * @v name Test name
+ * @v PUBKEY Public-key algorithm
+ * @v PRIVATE Private key
+ * @v PUBLIC Public key
+ * @v PLAINTEXT Plaintext
+ * @v DIGEST Digest algorithm
+ * @v SIGNATURE Signature
+ * @ret test Signature test
*/
-#define pubkey_sign_ok( pubkey, key, key_len, digest, plaintext, \
- plaintext_len, expected, expected_len ) do { \
- uint8_t ctx[ (pubkey)->ctxsize ]; \
- uint8_t digestctx[ (digest)->ctxsize ]; \
- uint8_t digestout[ (digest)->digestsize ]; \
- \
- digest_init ( (digest), digestctx ); \
- digest_update ( (digest), digestctx, (plaintext), \
- (plaintext_len) ); \
- digest_final ( (digest), digestctx, digestout ); \
- \
- ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \
- { \
- size_t max_len = pubkey_max_len ( (pubkey), ctx ); \
- uint8_t signature[ max_len ]; \
- int signature_len; \
- \
- signature_len = pubkey_sign ( (pubkey), ctx, (digest), \
- digestout, signature ); \
- ok ( signature_len == ( ( int ) (expected_len) ) ); \
- ok ( memcmp ( signature, (expected), \
- (expected_len) ) == 0 ); \
- } \
- pubkey_final ( (pubkey), ctx ); \
- } while ( 0 )
+#define PUBKEY_SIGN_TEST( name, PUBKEY, PRIVATE, PUBLIC, PLAINTEXT, \
+ DIGEST, SIGNATURE ) \
+ static const uint8_t name ## _private[] = PRIVATE; \
+ static const uint8_t name ## _public[] = PUBLIC; \
+ static const uint8_t name ## _plaintext[] = PLAINTEXT; \
+ static const uint8_t name ## _signature[] = SIGNATURE; \
+ static struct pubkey_sign_test name = { \
+ .pubkey = PUBKEY, \
+ .private = { \
+ .data = name ## _private, \
+ .len = sizeof ( name ## _private ), \
+ }, \
+ .public = { \
+ .data = name ## _public, \
+ .len = sizeof ( name ## _public ), \
+ }, \
+ .plaintext = name ## _plaintext, \
+ .plaintext_len = sizeof ( name ## _plaintext ), \
+ .digest = DIGEST, \
+ .signature = name ## _signature, \
+ .signature_len = sizeof ( name ## _signature ), \
+ }
+
+extern void pubkey_okx ( struct pubkey_test *test,
+ const char *file, unsigned int line );
+extern void pubkey_sign_okx ( struct pubkey_sign_test *test,
+ const char *file, unsigned int line );
/**
- * Report public key verification test result
+ * Report a public key encryption and decryption test result
*
- * @v pubkey Public key algorithm
- * @v key Key
- * @v key_len Key length
- * @v digest Digest algorithm
- * @v plaintext Plaintext
- * @v plaintext_len Plaintext length
- * @v signature Signature
- * @v signature_len Signature length
+ * @v test Public key encryption and decryption test
*/
-#define pubkey_verify_ok( pubkey, key, key_len, digest, plaintext, \
- plaintext_len, signature, signature_len ) do {\
- uint8_t ctx[ (pubkey)->ctxsize ]; \
- uint8_t digestctx[ (digest)->ctxsize ]; \
- uint8_t digestout[ (digest)->digestsize ]; \
- \
- digest_init ( (digest), digestctx ); \
- digest_update ( (digest), digestctx, (plaintext), \
- (plaintext_len) ); \
- digest_final ( (digest), digestctx, digestout ); \
- \
- ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \
- ok ( pubkey_verify ( (pubkey), ctx, (digest), digestout, \
- (signature), (signature_len) ) == 0 ); \
- pubkey_final ( (pubkey), ctx ); \
- } while ( 0 )
+#define pubkey_ok( test ) \
+ pubkey_okx ( test, __FILE__, __LINE__ )
/**
- * Report public key verification test result
+ * Report a public key signature test result
*
- * @v pubkey Public key algorithm
- * @v key Key
- * @v key_len Key length
- * @v digest Digest algorithm
- * @v plaintext Plaintext
- * @v plaintext_len Plaintext length
- * @v signature Signature
- * @v signature_len Signature length
+ * @v test Public key signature test
*/
-#define pubkey_verify_fail_ok( pubkey, key, key_len, digest, plaintext, \
- plaintext_len, signature, \
- signature_len ) do { \
- uint8_t ctx[ (pubkey)->ctxsize ]; \
- uint8_t digestctx[ (digest)->ctxsize ]; \
- uint8_t digestout[ (digest)->digestsize ]; \
- \
- digest_init ( (digest), digestctx ); \
- digest_update ( (digest), digestctx, (plaintext), \
- (plaintext_len) ); \
- digest_final ( (digest), digestctx, digestout ); \
- \
- ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \
- ok ( pubkey_verify ( (pubkey), ctx, (digest), digestout, \
- (signature), (signature_len) ) != 0 ); \
- pubkey_final ( (pubkey), ctx ); \
- } while ( 0 )
+#define pubkey_sign_ok( test ) \
+ pubkey_sign_okx ( test, __FILE__, __LINE__ )
#endif /* _PUBKEY_TEST_H */
diff --git a/src/tests/rsa_test.c b/src/tests/rsa_test.c
index 46894f6..1316093 100644
--- a/src/tests/rsa_test.c
+++ b/src/tests/rsa_test.c
@@ -43,171 +43,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/test.h>
#include "pubkey_test.h"
-/** Define inline private key data */
-#define PRIVATE(...) { __VA_ARGS__ }
-
-/** Define inline public key data */
-#define PUBLIC(...) { __VA_ARGS__ }
-
-/** Define inline plaintext data */
-#define PLAINTEXT(...) { __VA_ARGS__ }
-
-/** Define inline ciphertext data */
-#define CIPHERTEXT(...) { __VA_ARGS__ }
-
-/** Define inline signature data */
-#define SIGNATURE(...) { __VA_ARGS__ }
-
-/** An RSA encryption and decryption self-test */
-struct rsa_encrypt_decrypt_test {
- /** Private key */
- const void *private;
- /** Private key length */
- size_t private_len;
- /** Public key */
- const void *public;
- /** Public key length */
- size_t public_len;
- /** Plaintext */
- const void *plaintext;
- /** Plaintext length */
- size_t plaintext_len;
- /** Ciphertext
- *
- * Note that the encryption process includes some random
- * padding, so a given plaintext will encrypt to multiple
- * different ciphertexts.
- */
- const void *ciphertext;
- /** Ciphertext length */
- size_t ciphertext_len;
-};
-
-/**
- * Define an RSA encryption and decryption test
- *
- * @v name Test name
- * @v PRIVATE Private key
- * @v PUBLIC Public key
- * @v PLAINTEXT Plaintext
- * @v CIPHERTEXT Ciphertext
- * @ret test Encryption and decryption test
- */
-#define RSA_ENCRYPT_DECRYPT_TEST( name, PRIVATE, PUBLIC, PLAINTEXT, \
- CIPHERTEXT ) \
- static const uint8_t name ## _private[] = PRIVATE; \
- static const uint8_t name ## _public[] = PUBLIC; \
- static const uint8_t name ## _plaintext[] = PLAINTEXT; \
- static const uint8_t name ## _ciphertext[] = CIPHERTEXT; \
- static struct rsa_encrypt_decrypt_test name = { \
- .private = name ## _private, \
- .private_len = sizeof ( name ## _private ), \
- .public = name ## _public, \
- .public_len = sizeof ( name ## _public ), \
- .plaintext = name ## _plaintext, \
- .plaintext_len = sizeof ( name ## _plaintext ), \
- .ciphertext = name ## _ciphertext, \
- .ciphertext_len = sizeof ( name ## _ciphertext ), \
- }
-
-/** An RSA signature self-test */
-struct rsa_signature_test {
- /** Private key */
- const void *private;
- /** Private key length */
- size_t private_len;
- /** Public key */
- const void *public;
- /** Public key length */
- size_t public_len;
- /** Plaintext */
- const void *plaintext;
- /** Plaintext length */
- size_t plaintext_len;
- /** Signature algorithm */
- struct asn1_algorithm *algorithm;
- /** Signature */
- const void *signature;
- /** Signature length */
- size_t signature_len;
-};
-
-/**
- * Define an RSA signature test
- *
- * @v name Test name
- * @v PRIVATE Private key
- * @v PUBLIC Public key
- * @v PLAINTEXT Plaintext
- * @v ALGORITHM Signature algorithm
- * @v SIGNATURE Signature
- * @ret test Signature test
- */
-#define RSA_SIGNATURE_TEST( name, PRIVATE, PUBLIC, PLAINTEXT, \
- ALGORITHM, SIGNATURE ) \
- static const uint8_t name ## _private[] = PRIVATE; \
- static const uint8_t name ## _public[] = PUBLIC; \
- static const uint8_t name ## _plaintext[] = PLAINTEXT; \
- static const uint8_t name ## _signature[] = SIGNATURE; \
- static struct rsa_signature_test name = { \
- .private = name ## _private, \
- .private_len = sizeof ( name ## _private ), \
- .public = name ## _public, \
- .public_len = sizeof ( name ## _public ), \
- .plaintext = name ## _plaintext, \
- .plaintext_len = sizeof ( name ## _plaintext ), \
- .algorithm = ALGORITHM, \
- .signature = name ## _signature, \
- .signature_len = sizeof ( name ## _signature ), \
- }
-
-/**
- * Report RSA encryption and decryption test result
- *
- * @v test RSA encryption and decryption test
- */
-#define rsa_encrypt_decrypt_ok( test ) do { \
- pubkey_decrypt_ok ( &rsa_algorithm, (test)->private, \
- (test)->private_len, (test)->ciphertext, \
- (test)->ciphertext_len, (test)->plaintext, \
- (test)->plaintext_len ); \
- pubkey_encrypt_ok ( &rsa_algorithm, (test)->private, \
- (test)->private_len, (test)->public, \
- (test)->public_len, (test)->plaintext, \
- (test)->plaintext_len ); \
- pubkey_encrypt_ok ( &rsa_algorithm, (test)->public, \
- (test)->public_len, (test)->private, \
- (test)->private_len, (test)->plaintext, \
- (test)->plaintext_len ); \
- } while ( 0 )
-
-
-/**
- * Report RSA signature test result
- *
- * @v test RSA signature test
- */
-#define rsa_signature_ok( test ) do { \
- struct digest_algorithm *digest = (test)->algorithm->digest; \
- uint8_t bad_signature[ (test)->signature_len ]; \
- pubkey_sign_ok ( &rsa_algorithm, (test)->private, \
- (test)->private_len, digest, \
- (test)->plaintext, (test)->plaintext_len, \
- (test)->signature, (test)->signature_len ); \
- pubkey_verify_ok ( &rsa_algorithm, (test)->public, \
- (test)->public_len, digest, \
- (test)->plaintext, (test)->plaintext_len, \
- (test)->signature, (test)->signature_len ); \
- memset ( bad_signature, 0, sizeof ( bad_signature ) ); \
- pubkey_verify_fail_ok ( &rsa_algorithm, (test)->public, \
- (test)->public_len, digest, \
- (test)->plaintext, \
- (test)->plaintext_len, bad_signature, \
- sizeof ( bad_signature ) ); \
- } while ( 0 )
-
/** "Hello world" encryption and decryption test (traditional PKCS#1 key) */
-RSA_ENCRYPT_DECRYPT_TEST ( hw_test,
+PUBKEY_TEST ( hw_test, &rsa_algorithm,
PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
0xd2, 0xf1, 0x04, 0x67, 0xf6, 0x2c, 0x96, 0x07, 0xa6, 0xbd,
0x85, 0xac, 0xc1, 0x17, 0x5d, 0xe8, 0xf0, 0x93, 0x94, 0x0c,
@@ -261,7 +98,7 @@ RSA_ENCRYPT_DECRYPT_TEST ( hw_test,
0x38, 0x43, 0xf9, 0x41 ) );
/** "Hello world" encryption and decryption test (PKCS#8 key) */
-RSA_ENCRYPT_DECRYPT_TEST ( hw_test_pkcs8,
+PUBKEY_TEST ( hw_test_pkcs8, &rsa_algorithm,
PRIVATE ( 0x30, 0x82, 0x01, 0x55, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06,
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
0x05, 0x00, 0x04, 0x82, 0x01, 0x3f, 0x30, 0x82, 0x01, 0x3b,
@@ -318,7 +155,7 @@ RSA_ENCRYPT_DECRYPT_TEST ( hw_test_pkcs8,
0x38, 0x43, 0xf9, 0x41 ) );
/** Random message MD5 signature test */
-RSA_SIGNATURE_TEST ( md5_test,
+PUBKEY_SIGN_TEST ( md5_test, &rsa_algorithm,
PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
0xf9, 0x3f, 0x78, 0x44, 0xe2, 0x0e, 0x25, 0xf1, 0x0e, 0x94,
0xcd, 0xca, 0x6f, 0x9e, 0xea, 0x6d, 0xdf, 0xcd, 0xa0, 0x7c,
@@ -381,7 +218,7 @@ RSA_SIGNATURE_TEST ( md5_test,
0xf2, 0x8d, 0xfc, 0xfc, 0x37, 0xf7, 0xc7, 0x6d, 0x6c, 0xd8,
0x24, 0x0c, 0x6a, 0xec, 0x82, 0x5c, 0x72, 0xf1, 0xfc, 0x05,
0xed, 0x8e, 0xe8, 0xd9, 0x8b, 0x8b, 0x67, 0x02, 0x95 ),
- &md5_with_rsa_encryption_algorithm,
+ &md5_algorithm,
SIGNATURE ( 0xdb, 0x56, 0x3d, 0xea, 0xae, 0x81, 0x4b, 0x3b, 0x2e, 0x8e,
0xb8, 0xee, 0x13, 0x61, 0xc6, 0xe7, 0xd7, 0x50, 0xcd, 0x0d,
0x34, 0x3a, 0xfe, 0x9a, 0x8d, 0xf8, 0xfb, 0xd6, 0x7e, 0xbd,
@@ -391,7 +228,7 @@ RSA_SIGNATURE_TEST ( md5_test,
0xac, 0x45, 0x00, 0xa8 ) );
/** Random message SHA-1 signature test */
-RSA_SIGNATURE_TEST ( sha1_test,
+PUBKEY_SIGN_TEST ( sha1_test, &rsa_algorithm,
PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
0xe0, 0x3a, 0x8d, 0x35, 0xe1, 0x92, 0x2f, 0xea, 0x0d, 0x82,
0x60, 0x2e, 0xb6, 0x0b, 0x02, 0xd3, 0xf4, 0x39, 0xfb, 0x06,
@@ -454,7 +291,7 @@ RSA_SIGNATURE_TEST ( sha1_test,
0x30, 0x91, 0x1c, 0xaa, 0x6c, 0x24, 0x42, 0x1b, 0x1a, 0xba,
0x30, 0x40, 0x49, 0x83, 0xd9, 0xd7, 0x66, 0x7e, 0x5c, 0x1a,
0x4b, 0x7f, 0xa6, 0x8e, 0x8a, 0xd6, 0x0c, 0x65, 0x75 ),
- &sha1_with_rsa_encryption_algorithm,
+ &sha1_algorithm,
SIGNATURE ( 0xa5, 0x5a, 0x8a, 0x67, 0x81, 0x76, 0x7e, 0xad, 0x99, 0x22,
0xf1, 0x47, 0x64, 0xd2, 0xfb, 0x81, 0x45, 0xeb, 0x85, 0x56,
0xf8, 0x7d, 0xb8, 0xec, 0x41, 0x17, 0x84, 0xf7, 0x2b, 0xbb,
@@ -464,7 +301,7 @@ RSA_SIGNATURE_TEST ( sha1_test,
0x0e, 0x3d, 0x80, 0x80 ) );
/** Random message SHA-256 signature test */
-RSA_SIGNATURE_TEST ( sha256_test,
+PUBKEY_SIGN_TEST ( sha256_test, &rsa_algorithm,
PRIVATE ( 0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
0xa5, 0xe9, 0xdb, 0xa9, 0x1a, 0x6e, 0xd6, 0x4c, 0x25, 0x50,
0xfe, 0x61, 0x77, 0x08, 0x7a, 0x80, 0x36, 0xcb, 0x88, 0x49,
@@ -527,7 +364,7 @@ RSA_SIGNATURE_TEST ( sha256_test,
0x91, 0x71, 0xd6, 0x2d, 0xa1, 0xae, 0x81, 0x0c, 0xed, 0x54,
0x48, 0x79, 0x8a, 0x78, 0x05, 0x74, 0x4d, 0x4f, 0xf0, 0xe0,
0x3c, 0x41, 0x5c, 0x04, 0x0b, 0x68, 0x57, 0xc5, 0xd6 ),
- &sha256_with_rsa_encryption_algorithm,
+ &sha256_algorithm,
SIGNATURE ( 0x02, 0x2e, 0xc5, 0x2a, 0x2b, 0x7f, 0xb4, 0x80, 0xca, 0x9d,
0x96, 0x5b, 0xaf, 0x1f, 0x72, 0x5b, 0x6e, 0xf1, 0x69, 0x7f,
0x4d, 0x41, 0xd5, 0x9f, 0x00, 0xdc, 0x47, 0xf4, 0x68, 0x8f,
@@ -542,11 +379,11 @@ RSA_SIGNATURE_TEST ( sha256_test,
*/
static void rsa_test_exec ( void ) {
- rsa_encrypt_decrypt_ok ( &hw_test );
- rsa_encrypt_decrypt_ok ( &hw_test_pkcs8 );
- rsa_signature_ok ( &md5_test );
- rsa_signature_ok ( &sha1_test );
- rsa_signature_ok ( &sha256_test );
+ pubkey_ok ( &hw_test );
+ pubkey_ok ( &hw_test_pkcs8 );
+ pubkey_sign_ok ( &md5_test );
+ pubkey_sign_ok ( &sha1_test );
+ pubkey_sign_ok ( &sha256_test );
}
/** RSA self-test */
@@ -554,3 +391,9 @@ struct self_test rsa_test __self_test = {
.name = "rsa",
.exec = rsa_test_exec,
};
+
+/* Drag in required ASN.1 OID-identified algorithms */
+REQUIRING_SYMBOL ( rsa_test );
+REQUIRE_OBJECT ( rsa_md5 );
+REQUIRE_OBJECT ( rsa_sha1 );
+REQUIRE_OBJECT ( rsa_sha256 );
diff --git a/src/usr/imgcrypt.c b/src/usr/imgcrypt.c
new file mode 100644
index 0000000..1b649f1
--- /dev/null
+++ b/src/usr/imgcrypt.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <string.h>
+#include <syslog.h>
+#include <ipxe/image.h>
+#include <ipxe/cms.h>
+#include <ipxe/privkey.h>
+#include <usr/imgcrypt.h>
+
+/** @file
+ *
+ * Image encryption management
+ *
+ */
+
+/**
+ * Decrypt image using downloaded envelope
+ *
+ * @v image Image to decrypt
+ * @v envelope Image containing decryption key
+ * @v name Decrypted image name (or NULL to use default)
+ * @ret rc Return status code
+ */
+int imgdecrypt ( struct image *image, struct image *envelope,
+ const char *name ) {
+ struct cms_message *cms;
+ int rc;
+
+ /* Parse envelope */
+ if ( ( rc = cms_message ( envelope, &cms ) ) != 0 )
+ goto err_parse;
+
+ /* Decrypt image */
+ if ( ( rc = cms_decrypt ( cms, image, name, &private_key ) ) != 0 )
+ goto err_decrypt;
+
+ /* Drop reference to message */
+ cms_put ( cms );
+ cms = NULL;
+
+ /* Record decryption */
+ syslog ( LOG_NOTICE, "Image \"%s\" decrypted OK\n", image->name );
+
+ return 0;
+
+ err_decrypt:
+ cms_put ( cms );
+ err_parse:
+ syslog ( LOG_ERR, "Image \"%s\" decryption failed: %s\n",
+ image->name, strerror ( rc ) );
+ return rc;
+}
diff --git a/src/usr/imgtrust.c b/src/usr/imgtrust.c
index e7c2067..7f7e7ed 100644
--- a/src/usr/imgtrust.c
+++ b/src/usr/imgtrust.c
@@ -50,34 +50,18 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
int imgverify ( struct image *image, struct image *signature,
const char *name ) {
- struct asn1_cursor *data;
- struct cms_signature *sig;
- struct cms_signer_info *info;
+ struct cms_message *cms;
+ struct cms_participant *part;
time_t now;
- int next;
int rc;
- /* Mark image as untrusted */
- image_untrust ( image );
-
- /* Get raw signature data */
- next = image_asn1 ( signature, 0, &data );
- if ( next < 0 ) {
- rc = next;
- goto err_asn1;
- }
-
/* Parse signature */
- if ( ( rc = cms_signature ( data->data, data->len, &sig ) ) != 0 )
+ if ( ( rc = cms_message ( signature, &cms ) ) != 0 )
goto err_parse;
- /* Free raw signature data */
- free ( data );
- data = NULL;
-
/* Complete all certificate chains */
- list_for_each_entry ( info, &sig->info, list ) {
- if ( ( rc = create_validator ( &monojob, info->chain,
+ list_for_each_entry ( part, &cms->participants, list ) {
+ if ( ( rc = create_validator ( &monojob, part->chain,
NULL ) ) != 0 )
goto err_create_validator;
if ( ( rc = monojob_wait ( NULL, 0 ) ) != 0 )
@@ -86,16 +70,14 @@ int imgverify ( struct image *image, struct image *signature,
/* Use signature to verify image */
now = time ( NULL );
- if ( ( rc = cms_verify ( sig, image->data, image->len,
- name, now, NULL, NULL ) ) != 0 )
+ if ( ( rc = cms_verify ( cms, image, name, now, NULL, NULL ) ) != 0 )
goto err_verify;
- /* Drop reference to signature */
- cms_put ( sig );
- sig = NULL;
+ /* Drop reference to message */
+ cms_put ( cms );
+ cms = NULL;
- /* Mark image as trusted */
- image_trust ( image );
+ /* Record signature verification */
syslog ( LOG_NOTICE, "Image \"%s\" signature OK\n", image->name );
return 0;
@@ -103,10 +85,8 @@ int imgverify ( struct image *image, struct image *signature,
err_verify:
err_validator_wait:
err_create_validator:
- cms_put ( sig );
+ cms_put ( cms );
err_parse:
- free ( data );
- err_asn1:
syslog ( LOG_ERR, "Image \"%s\" signature bad: %s\n",
image->name, strerror ( rc ) );
return rc;