]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Switch to using python-asn1crypto instead of python-asn1
authorMichael Brown <mcb30@ipxe.org>
Fri, 11 Apr 2025 11:36:45 +0000 (12:36 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 11 Apr 2025 11:40:22 +0000 (12:40 +0100)
Version 3.0.0 of python-asn1 has a serious defect that causes it to
generate invalid DER.

Fix by switching to the asn1crypto module, which also allows for
simpler code to be used.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
contrib/crypto/cmsdetach

index fdd8889589a8f5c77ff15563e0e7c57ed38fbc54..a48d30c67a9c18c5014123f9c567190fd9b14b14 100755 (executable)
@@ -7,8 +7,9 @@ message into a separate file.
 """
 
 import argparse
+from pathlib import Path
 
-import asn1
+from asn1crypto.cms import ContentInfo, AuthEnvelopedData, EnvelopedData
 
 # Parse command-line arguments
 #
@@ -16,64 +17,45 @@ parser = argparse.ArgumentParser(
     description=__doc__,
     formatter_class=argparse.RawDescriptionHelpFormatter,
 )
-parser.add_argument("-d", "--data", metavar="FILE",
+parser.add_argument("-d", "--data", metavar="FILE", type=Path,
                     help="Write detached data (without envelope) to FILE")
-parser.add_argument("-e", "--envelope", metavar="FILE",
+parser.add_argument("-e", "--envelope", metavar="FILE", type=Path,
                     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")
+parser.add_argument("file", type=Path, 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
+# Read input envelope
 #
-decoder = asn1.Decoder()
-with open(args.file, mode="rb") as fh:
-    decoder.start(fh.read())
+envelope = ContentInfo.load(args.file.read_bytes())
 
-# Create encoder
+# Locate encrypted content info
 #
-encoder = asn1.Encoder()
-encoder.start()
+content = envelope["content"]
+if type(content) is AuthEnvelopedData:
+    encinfo = content["auth_encrypted_content_info"]
+elif type(content) is EnvelopedData:
+    encinfo = content["encrypted_content_info"]
+else:
+    parser.error("Input file does not contain any encrypted data")
 
-# Detach encrypted data
+# Detach encrypted content data
 #
-data = None
-datastack = [
-    asn1.Numbers.Sequence, 0, asn1.Numbers.Sequence, asn1.Numbers.Sequence
-]
-stack = []
-while stack or not decoder.eof():
-    tag = decoder.peek()
-    if tag is None:
-        encoder.leave()
-        decoder.leave()
-        stack.pop()
-    elif 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")
+data = encinfo["encrypted_content"]
+del encinfo["encrypted_content"]
 
 # Write envelope (without data), if applicable
 #
 if args.envelope:
-    with open(args.envelope, mode=outmode) as fh:
-        fh.write(envelope)
+    with args.envelope.open(mode=outmode) as fh:
+        fh.write(envelope.dump())
 
 # Write data (without envelope), if applicable
 #
 if args.data:
-    with open(args.data, mode=outmode) as fh:
-        fh.write(data)
+    with args.data.open(mode=outmode) as fh:
+        fh.write(data.contents)