diff options
author | Michael Brown <mcb30@ipxe.org> | 2024-08-28 16:09:55 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2024-08-28 16:17:14 +0100 |
commit | 748cab7745186ec6c770fb4d47b0e8c9f213e6df (patch) | |
tree | c2a79df91cc7b69aec6423c3949a02f6262b64b0 | |
parent | b053ba19884415794504c1bcffa910f0295598f0 (diff) | |
download | ipxe-748cab7745186ec6c770fb4d47b0e8c9f213e6df.tar.gz |
[crypto] Add cmsdetach script for detaching encrypted data from CMS messages
The openssl toolchain does not currently seem to support creating CMS
envelopedData or authEnvelopedData messages with detached encrypted
data.
Add a standalone tool "cmsdetach" that can be used to detach the
encrypted data from a CMS message. For example:
openssl cms -encrypt -binary -aes-256-gcm -recip client.crt \
-in bootfile -outform DER -out bootfile.cms
cmsdetach bootfile.cms --data bootfile.dat --envelope bootfile.env
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rwxr-xr-x | contrib/crypto/cmsdetach | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/contrib/crypto/cmsdetach b/contrib/crypto/cmsdetach new file mode 100755 index 000000000..007500996 --- /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) |