Linux-Modules Archive on lore.kernel.org
 help / Atom feed
* [PATCH RFC PKCS7 asn1c 0/2] asn1c version of PKCS#7 parser
@ 2018-03-08 13:58 Yauheni Kaliuta
  2018-03-08 13:58 ` [PATCH RFC PKCS7 asn1c 2/2] libkmod, pkcs7: commit asn1c autogenerated files Yauheni Kaliuta
  2018-03-12 15:42 ` [PATCH RFC PKCS7 asn1c 0/2] asn1c version of PKCS#7 parser Michal Suchánek
  0 siblings, 2 replies; 13+ messages in thread
From: Yauheni Kaliuta @ 2018-03-08 13:58 UTC (permalink / raw)
  To: Lucas De Marchi
  Cc: linux-modules, Ferry van Steen, David Howells, Michal Suchanek

Draft implementation of possible PKCS7 signature parser for
modinfo.  I'm pretty bad in autotools, so would be fine if
somebody integrate it inside properly.

What bothers me is that asn1c files are generated under BSD
license.

Yauheni Kaliuta (2):
  libkmod-signature: implement pkcs7 parsing with asn1c compiler
  libkmod, pkcs7: commit asn1c autogenerated files

 Makefile.am                                        |   22 +-
 configure.ac                                       |    1 +
 libkmod/libkmod-internal.h                         |    3 +
 libkmod/libkmod-module.c                           |    3 +
 libkmod/libkmod-signature.c                        |  105 +-
 libkmod/pkcs7/asn1c-gen/ANY.c                      |  158 ++
 libkmod/pkcs7/asn1c-gen/ANY.h                      |   48 +
 libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c  |   68 +
 libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h  |   40 +
 libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c   |   69 +
 libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h   |   40 +
 libkmod/pkcs7/asn1c-gen/BIT_STRING.c               |  189 ++
 libkmod/pkcs7/asn1c-gen/BIT_STRING.h               |   33 +
 libkmod/pkcs7/asn1c-gen/CRLSequence.c              |   52 +
 libkmod/pkcs7/asn1c-gen/CRLSequence.h              |   44 +
 libkmod/pkcs7/asn1c-gen/Certificate.c              |  104 ++
 libkmod/pkcs7/asn1c-gen/Certificate.h              |   39 +
 libkmod/pkcs7/asn1c-gen/CertificateList.c          |   52 +
 libkmod/pkcs7/asn1c-gen/CertificateList.h          |   39 +
 .../pkcs7/asn1c-gen/CertificateRevocationLists.c   |   52 +
 .../pkcs7/asn1c-gen/CertificateRevocationLists.h   |   44 +
 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c  |  109 ++
 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h  |   39 +
 libkmod/pkcs7/asn1c-gen/Certificates.c             |   52 +
 libkmod/pkcs7/asn1c-gen/Certificates.h             |   39 +
 libkmod/pkcs7/asn1c-gen/ContentInfo.c              |   69 +
 libkmod/pkcs7/asn1c-gen/ContentInfo.h              |   40 +
 libkmod/pkcs7/asn1c-gen/ContentType.c              |  109 ++
 libkmod/pkcs7/asn1c-gen/ContentType.h              |   39 +
 libkmod/pkcs7/asn1c-gen/Data.c                     |  104 ++
 libkmod/pkcs7/asn1c-gen/Data.h                     |   39 +
 .../pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c    |   68 +
 .../pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h    |   40 +
 .../pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c   |  153 ++
 .../pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h   |   68 +
 .../DigestEncryptionAlgorithmIdentifier.c          |   68 +
 .../DigestEncryptionAlgorithmIdentifier.h          |   40 +
 libkmod/pkcs7/asn1c-gen/EncryptedDigest.c          |  109 ++
 libkmod/pkcs7/asn1c-gen/EncryptedDigest.h          |   39 +
 .../ExtendedCertificatesAndCertificates.c          |   52 +
 .../ExtendedCertificatesAndCertificates.h          |   39 +
 libkmod/pkcs7/asn1c-gen/INTEGER.c                  | 1025 +++++++++++
 libkmod/pkcs7/asn1c-gen/INTEGER.h                  |   82 +
 libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c    |   65 +
 libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h    |   39 +
 libkmod/pkcs7/asn1c-gen/Makefile.am                |  131 ++
 libkmod/pkcs7/asn1c-gen/Makefile.am.sample         |  150 ++
 libkmod/pkcs7/asn1c-gen/Name.c                     |   52 +
 libkmod/pkcs7/asn1c-gen/Name.h                     |   44 +
 libkmod/pkcs7/asn1c-gen/NativeEnumerated.c         |  207 +++
 libkmod/pkcs7/asn1c-gen/NativeEnumerated.h         |   32 +
 libkmod/pkcs7/asn1c-gen/NativeInteger.c            |  332 ++++
 libkmod/pkcs7/asn1c-gen/NativeInteger.h            |   37 +
 libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c        |  764 +++++++++
 libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h        |  139 ++
 libkmod/pkcs7/asn1c-gen/OCTET_STRING.c             | 1807 ++++++++++++++++++++
 libkmod/pkcs7/asn1c-gen/OCTET_STRING.h             |   86 +
 libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c         |   69 +
 libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h         |   45 +
 .../pkcs7/asn1c-gen/RelativeDistinguishedName.c    |   52 +
 .../pkcs7/asn1c-gen/RelativeDistinguishedName.h    |   44 +
 .../pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c  |   52 +
 .../pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h  |   44 +
 libkmod/pkcs7/asn1c-gen/SignedData.c               |  227 +++
 libkmod/pkcs7/asn1c-gen/SignedData.h               |   81 +
 libkmod/pkcs7/asn1c-gen/SignerIdentifier.c         |   65 +
 libkmod/pkcs7/asn1c-gen/SignerIdentifier.h         |   50 +
 libkmod/pkcs7/asn1c-gen/SignerInfo.c               |  371 ++++
 libkmod/pkcs7/asn1c-gen/SignerInfo.h               |  107 ++
 libkmod/pkcs7/asn1c-gen/SignerInfos.c              |  153 ++
 libkmod/pkcs7/asn1c-gen/SignerInfos.h              |   68 +
 libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c     |  109 ++
 libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h     |   39 +
 libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c |   69 +
 libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h |   40 +
 libkmod/pkcs7/asn1c-gen/Values.c                   |   52 +
 libkmod/pkcs7/asn1c-gen/Values.h                   |   39 +
 libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c          |   41 +
 libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h          |   52 +
 libkmod/pkcs7/asn1c-gen/asn_SET_OF.c               |   88 +
 libkmod/pkcs7/asn1c-gen/asn_SET_OF.h               |   62 +
 libkmod/pkcs7/asn1c-gen/asn_application.h          |   47 +
 libkmod/pkcs7/asn1c-gen/asn_codecs.h               |  109 ++
 libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c          |  312 ++++
 libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h          |   53 +
 libkmod/pkcs7/asn1c-gen/asn_internal.h             |  128 ++
 libkmod/pkcs7/asn1c-gen/asn_system.h               |  137 ++
 libkmod/pkcs7/asn1c-gen/ber_decoder.c              |  283 +++
 libkmod/pkcs7/asn1c-gen/ber_decoder.h              |   64 +
 libkmod/pkcs7/asn1c-gen/ber_tlv_length.c           |  178 ++
 libkmod/pkcs7/asn1c-gen/ber_tlv_length.h           |   50 +
 libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c              |  144 ++
 libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h              |   60 +
 libkmod/pkcs7/asn1c-gen/constr_CHOICE.c            | 1114 ++++++++++++
 libkmod/pkcs7/asn1c-gen/constr_CHOICE.h            |   57 +
 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c          | 1425 +++++++++++++++
 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h          |   60 +
 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c       |  208 +++
 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h       |   33 +
 libkmod/pkcs7/asn1c-gen/constr_SET_OF.c            |  954 +++++++++++
 libkmod/pkcs7/asn1c-gen/constr_SET_OF.h            |   42 +
 libkmod/pkcs7/asn1c-gen/constr_TYPE.c              |   77 +
 libkmod/pkcs7/asn1c-gen/constr_TYPE.h              |  180 ++
 libkmod/pkcs7/asn1c-gen/constraints.c              |   93 +
 libkmod/pkcs7/asn1c-gen/constraints.h              |   63 +
 libkmod/pkcs7/asn1c-gen/converter-sample.c         |  834 +++++++++
 libkmod/pkcs7/asn1c-gen/der_encoder.c              |  201 +++
 libkmod/pkcs7/asn1c-gen/der_encoder.h              |   68 +
 libkmod/pkcs7/asn1c-gen/per_decoder.c              |   93 +
 libkmod/pkcs7/asn1c-gen/per_decoder.h              |   56 +
 libkmod/pkcs7/asn1c-gen/per_encoder.c              |  151 ++
 libkmod/pkcs7/asn1c-gen/per_encoder.h              |   69 +
 libkmod/pkcs7/asn1c-gen/per_opentype.c             |  378 ++++
 libkmod/pkcs7/asn1c-gen/per_opentype.h             |   22 +
 libkmod/pkcs7/asn1c-gen/per_support.c              |  483 ++++++
 libkmod/pkcs7/asn1c-gen/per_support.h              |  135 ++
 libkmod/pkcs7/asn1c-gen/xer_decoder.c              |  368 ++++
 libkmod/pkcs7/asn1c-gen/xer_decoder.h              |  106 ++
 libkmod/pkcs7/asn1c-gen/xer_encoder.c              |   67 +
 libkmod/pkcs7/asn1c-gen/xer_encoder.h              |   59 +
 libkmod/pkcs7/asn1c-gen/xer_support.c              |  227 +++
 libkmod/pkcs7/asn1c-gen/xer_support.h              |   55 +
 libkmod/pkcs7/pkcs7.asn1                           |  135 ++
 libkmod/pkcs7/pkcs7_parser.c                       |  297 ++++
 libkmod/pkcs7/pkcs7_parser.h                       |   42 +
 125 files changed, 19228 insertions(+), 20 deletions(-)
 create mode 100644 libkmod/pkcs7/asn1c-gen/ANY.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ANY.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/BIT_STRING.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/BIT_STRING.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/CRLSequence.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/CRLSequence.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Certificate.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Certificate.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateList.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateList.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Certificates.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Certificates.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ContentInfo.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ContentInfo.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ContentType.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ContentType.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Data.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Data.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/EncryptedDigest.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/EncryptedDigest.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/INTEGER.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/INTEGER.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Makefile.am
 create mode 100644 libkmod/pkcs7/asn1c-gen/Makefile.am.sample
 create mode 100644 libkmod/pkcs7/asn1c-gen/Name.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Name.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/NativeEnumerated.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/NativeEnumerated.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/NativeInteger.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/NativeInteger.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/OCTET_STRING.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/OCTET_STRING.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignedData.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignedData.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerIdentifier.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerIdentifier.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerInfo.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerInfo.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerInfos.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerInfos.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Values.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Values.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_SET_OF.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_SET_OF.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_application.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_codecs.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_internal.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_system.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_decoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_decoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_tlv_length.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_tlv_length.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_CHOICE.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_CHOICE.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SET_OF.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SET_OF.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_TYPE.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_TYPE.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constraints.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constraints.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/converter-sample.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/der_encoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/der_encoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_decoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_decoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_encoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_encoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_opentype.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_opentype.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_support.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_support.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_decoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_decoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_encoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_encoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_support.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_support.h
 create mode 100644 libkmod/pkcs7/pkcs7.asn1
 create mode 100644 libkmod/pkcs7/pkcs7_parser.c
 create mode 100644 libkmod/pkcs7/pkcs7_parser.h

-- 
2.16.2

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH RFC PKCS7 asn1c 2/2] libkmod, pkcs7: commit asn1c autogenerated files
  2018-03-08 13:58 [PATCH RFC PKCS7 asn1c 0/2] asn1c version of PKCS#7 parser Yauheni Kaliuta
@ 2018-03-08 13:58 ` Yauheni Kaliuta
  2018-03-12 15:45   ` Michal Suchánek
  2018-03-12 15:42 ` [PATCH RFC PKCS7 asn1c 0/2] asn1c version of PKCS#7 parser Michal Suchánek
  1 sibling, 1 reply; 13+ messages in thread
From: Yauheni Kaliuta @ 2018-03-08 13:58 UTC (permalink / raw)
  To: Lucas De Marchi
  Cc: linux-modules, Ferry van Steen, David Howells, Michal Suchanek

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
---
 libkmod/pkcs7/asn1c-gen/ANY.c                      |  158 ++
 libkmod/pkcs7/asn1c-gen/ANY.h                      |   48 +
 libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c  |   68 +
 libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h  |   40 +
 libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c   |   69 +
 libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h   |   40 +
 libkmod/pkcs7/asn1c-gen/BIT_STRING.c               |  189 ++
 libkmod/pkcs7/asn1c-gen/BIT_STRING.h               |   33 +
 libkmod/pkcs7/asn1c-gen/CRLSequence.c              |   52 +
 libkmod/pkcs7/asn1c-gen/CRLSequence.h              |   44 +
 libkmod/pkcs7/asn1c-gen/Certificate.c              |  104 ++
 libkmod/pkcs7/asn1c-gen/Certificate.h              |   39 +
 libkmod/pkcs7/asn1c-gen/CertificateList.c          |   52 +
 libkmod/pkcs7/asn1c-gen/CertificateList.h          |   39 +
 .../pkcs7/asn1c-gen/CertificateRevocationLists.c   |   52 +
 .../pkcs7/asn1c-gen/CertificateRevocationLists.h   |   44 +
 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c  |  109 ++
 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h  |   39 +
 libkmod/pkcs7/asn1c-gen/Certificates.c             |   52 +
 libkmod/pkcs7/asn1c-gen/Certificates.h             |   39 +
 libkmod/pkcs7/asn1c-gen/ContentInfo.c              |   69 +
 libkmod/pkcs7/asn1c-gen/ContentInfo.h              |   40 +
 libkmod/pkcs7/asn1c-gen/ContentType.c              |  109 ++
 libkmod/pkcs7/asn1c-gen/ContentType.h              |   39 +
 libkmod/pkcs7/asn1c-gen/Data.c                     |  104 ++
 libkmod/pkcs7/asn1c-gen/Data.h                     |   39 +
 .../pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c    |   68 +
 .../pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h    |   40 +
 .../pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c   |  153 ++
 .../pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h   |   68 +
 .../DigestEncryptionAlgorithmIdentifier.c          |   68 +
 .../DigestEncryptionAlgorithmIdentifier.h          |   40 +
 libkmod/pkcs7/asn1c-gen/EncryptedDigest.c          |  109 ++
 libkmod/pkcs7/asn1c-gen/EncryptedDigest.h          |   39 +
 .../ExtendedCertificatesAndCertificates.c          |   52 +
 .../ExtendedCertificatesAndCertificates.h          |   39 +
 libkmod/pkcs7/asn1c-gen/INTEGER.c                  | 1025 +++++++++++
 libkmod/pkcs7/asn1c-gen/INTEGER.h                  |   82 +
 libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c    |   65 +
 libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h    |   39 +
 libkmod/pkcs7/asn1c-gen/Makefile.am.sample         |  150 ++
 libkmod/pkcs7/asn1c-gen/Name.c                     |   52 +
 libkmod/pkcs7/asn1c-gen/Name.h                     |   44 +
 libkmod/pkcs7/asn1c-gen/NativeEnumerated.c         |  207 +++
 libkmod/pkcs7/asn1c-gen/NativeEnumerated.h         |   32 +
 libkmod/pkcs7/asn1c-gen/NativeInteger.c            |  332 ++++
 libkmod/pkcs7/asn1c-gen/NativeInteger.h            |   37 +
 libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c        |  764 +++++++++
 libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h        |  139 ++
 libkmod/pkcs7/asn1c-gen/OCTET_STRING.c             | 1807 ++++++++++++++++++++
 libkmod/pkcs7/asn1c-gen/OCTET_STRING.h             |   86 +
 libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c         |   69 +
 libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h         |   45 +
 .../pkcs7/asn1c-gen/RelativeDistinguishedName.c    |   52 +
 .../pkcs7/asn1c-gen/RelativeDistinguishedName.h    |   44 +
 .../pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c  |   52 +
 .../pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h  |   44 +
 libkmod/pkcs7/asn1c-gen/SignedData.c               |  227 +++
 libkmod/pkcs7/asn1c-gen/SignedData.h               |   81 +
 libkmod/pkcs7/asn1c-gen/SignerIdentifier.c         |   65 +
 libkmod/pkcs7/asn1c-gen/SignerIdentifier.h         |   50 +
 libkmod/pkcs7/asn1c-gen/SignerInfo.c               |  371 ++++
 libkmod/pkcs7/asn1c-gen/SignerInfo.h               |  107 ++
 libkmod/pkcs7/asn1c-gen/SignerInfos.c              |  153 ++
 libkmod/pkcs7/asn1c-gen/SignerInfos.h              |   68 +
 libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c     |  109 ++
 libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h     |   39 +
 libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c |   69 +
 libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h |   40 +
 libkmod/pkcs7/asn1c-gen/Values.c                   |   52 +
 libkmod/pkcs7/asn1c-gen/Values.h                   |   39 +
 libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c          |   41 +
 libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h          |   52 +
 libkmod/pkcs7/asn1c-gen/asn_SET_OF.c               |   88 +
 libkmod/pkcs7/asn1c-gen/asn_SET_OF.h               |   62 +
 libkmod/pkcs7/asn1c-gen/asn_application.h          |   47 +
 libkmod/pkcs7/asn1c-gen/asn_codecs.h               |  109 ++
 libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c          |  312 ++++
 libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h          |   53 +
 libkmod/pkcs7/asn1c-gen/asn_internal.h             |  128 ++
 libkmod/pkcs7/asn1c-gen/asn_system.h               |  137 ++
 libkmod/pkcs7/asn1c-gen/ber_decoder.c              |  283 +++
 libkmod/pkcs7/asn1c-gen/ber_decoder.h              |   64 +
 libkmod/pkcs7/asn1c-gen/ber_tlv_length.c           |  178 ++
 libkmod/pkcs7/asn1c-gen/ber_tlv_length.h           |   50 +
 libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c              |  144 ++
 libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h              |   60 +
 libkmod/pkcs7/asn1c-gen/constr_CHOICE.c            | 1114 ++++++++++++
 libkmod/pkcs7/asn1c-gen/constr_CHOICE.h            |   57 +
 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c          | 1425 +++++++++++++++
 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h          |   60 +
 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c       |  208 +++
 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h       |   33 +
 libkmod/pkcs7/asn1c-gen/constr_SET_OF.c            |  954 +++++++++++
 libkmod/pkcs7/asn1c-gen/constr_SET_OF.h            |   42 +
 libkmod/pkcs7/asn1c-gen/constr_TYPE.c              |   77 +
 libkmod/pkcs7/asn1c-gen/constr_TYPE.h              |  180 ++
 libkmod/pkcs7/asn1c-gen/constraints.c              |   93 +
 libkmod/pkcs7/asn1c-gen/constraints.h              |   63 +
 libkmod/pkcs7/asn1c-gen/converter-sample.c         |  834 +++++++++
 libkmod/pkcs7/asn1c-gen/der_encoder.c              |  201 +++
 libkmod/pkcs7/asn1c-gen/der_encoder.h              |   68 +
 libkmod/pkcs7/asn1c-gen/per_decoder.c              |   93 +
 libkmod/pkcs7/asn1c-gen/per_decoder.h              |   56 +
 libkmod/pkcs7/asn1c-gen/per_encoder.c              |  151 ++
 libkmod/pkcs7/asn1c-gen/per_encoder.h              |   69 +
 libkmod/pkcs7/asn1c-gen/per_opentype.c             |  378 ++++
 libkmod/pkcs7/asn1c-gen/per_opentype.h             |   22 +
 libkmod/pkcs7/asn1c-gen/per_support.c              |  483 ++++++
 libkmod/pkcs7/asn1c-gen/per_support.h              |  135 ++
 libkmod/pkcs7/asn1c-gen/xer_decoder.c              |  368 ++++
 libkmod/pkcs7/asn1c-gen/xer_decoder.h              |  106 ++
 libkmod/pkcs7/asn1c-gen/xer_encoder.c              |   67 +
 libkmod/pkcs7/asn1c-gen/xer_encoder.h              |   59 +
 libkmod/pkcs7/asn1c-gen/xer_support.c              |  227 +++
 libkmod/pkcs7/asn1c-gen/xer_support.h              |   55 +
 116 files changed, 18509 insertions(+)
 create mode 100644 libkmod/pkcs7/asn1c-gen/ANY.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ANY.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/BIT_STRING.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/BIT_STRING.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/CRLSequence.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/CRLSequence.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Certificate.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Certificate.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateList.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateList.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Certificates.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Certificates.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ContentInfo.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ContentInfo.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ContentType.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ContentType.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Data.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Data.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/EncryptedDigest.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/EncryptedDigest.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/INTEGER.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/INTEGER.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Makefile.am.sample
 create mode 100644 libkmod/pkcs7/asn1c-gen/Name.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Name.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/NativeEnumerated.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/NativeEnumerated.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/NativeInteger.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/NativeInteger.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/OCTET_STRING.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/OCTET_STRING.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignedData.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignedData.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerIdentifier.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerIdentifier.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerInfo.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerInfo.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerInfos.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SignerInfos.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/Values.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/Values.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_SET_OF.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_SET_OF.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_application.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_codecs.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_internal.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/asn_system.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_decoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_decoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_tlv_length.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_tlv_length.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_CHOICE.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_CHOICE.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SET_OF.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_SET_OF.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_TYPE.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constr_TYPE.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/constraints.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/constraints.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/converter-sample.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/der_encoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/der_encoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_decoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_decoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_encoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_encoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_opentype.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_opentype.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_support.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/per_support.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_decoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_decoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_encoder.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_encoder.h
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_support.c
 create mode 100644 libkmod/pkcs7/asn1c-gen/xer_support.h

diff --git a/libkmod/pkcs7/asn1c-gen/ANY.c b/libkmod/pkcs7/asn1c-gen/ANY.c
new file mode 100644
index 000000000000..77024bdcf3c9
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ANY.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <ANY.h>
+#include <errno.h>
+
+static asn_OCTET_STRING_specifics_t asn_DEF_ANY_specs = {
+	sizeof(ANY_t),
+	offsetof(ANY_t, _asn_ctx),
+	ASN_OSUBV_ANY
+};
+asn_TYPE_descriptor_t asn_DEF_ANY = {
+	"ANY",
+	"ANY",
+	OCTET_STRING_free,
+	OCTET_STRING_print,
+	asn_generic_no_constraint,
+	OCTET_STRING_decode_ber,
+	OCTET_STRING_encode_der,
+	OCTET_STRING_decode_xer_hex,
+	ANY_encode_xer,
+	0, 0,
+	0, /* Use generic outmost tag fetcher */
+	0, 0, 0, 0,
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	&asn_DEF_ANY_specs,
+};
+
+
+asn_enc_rval_t
+ANY_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+
+	if(flags & XER_F_CANONICAL) {
+		/*
+		 * Canonical XER-encoding of ANY type is not supported.
+		 */
+		ASN__ENCODE_FAILED;
+	}
+
+	/* Dump as binary */
+	return OCTET_STRING_encode_xer(td, sptr, ilevel, flags, cb, app_key);
+}
+
+struct _callback_arg {
+	uint8_t *buffer;
+	size_t offset;
+	size_t size;
+};
+
+static int ANY__consume_bytes(const void *buffer, size_t size, void *key);
+
+int
+ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
+	struct _callback_arg arg;
+	asn_enc_rval_t erval;
+
+	if(!st || !td) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if(!sptr) {
+		if(st->buf) FREEMEM(st->buf);
+		st->size = 0;
+		return 0;
+	}
+
+	arg.offset = arg.size = 0;
+	arg.buffer = 0;
+
+	erval = der_encode(td, sptr, ANY__consume_bytes, &arg);
+	if(erval.encoded == -1) {
+		if(arg.buffer) FREEMEM(arg.buffer);
+		return -1;
+	}
+	assert((size_t)erval.encoded == arg.offset);
+
+	if(st->buf) FREEMEM(st->buf);
+	st->buf = arg.buffer;
+	st->size = arg.offset;
+
+	return 0;
+}
+
+ANY_t *
+ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
+	ANY_t tmp;
+	ANY_t *st;
+
+	if(!td || !sptr) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	if(ANY_fromType(&tmp, td, sptr)) return 0;
+
+	st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
+	if(st) {
+		*st = tmp;
+		return st;
+	} else {
+		FREEMEM(tmp.buf);
+		return 0;
+	}
+}
+
+int
+ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
+	asn_dec_rval_t rval;
+	void *newst = 0;
+
+	if(!st || !td || !struct_ptr) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if(st->buf == 0) {
+		/* Nothing to convert, make it empty. */
+		*struct_ptr = (void *)0;
+		return 0;
+	}
+
+	rval = ber_decode(0, td, (void **)&newst, st->buf, st->size);
+	if(rval.code == RC_OK) {
+		*struct_ptr = newst;
+		return 0;
+	} else {
+		/* Remove possibly partially decoded data. */
+		ASN_STRUCT_FREE(*td, newst);
+		return -1;
+	}
+}
+
+static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
+	struct _callback_arg *arg = (struct _callback_arg *)key;
+
+	if((arg->offset + size) >= arg->size) {
+		size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
+		void *p = REALLOC(arg->buffer, nsize);
+		if(!p) return -1;
+		arg->buffer = (uint8_t *)p;
+		arg->size = nsize;
+	}
+
+	memcpy(arg->buffer + arg->offset, buffer, size);
+	arg->offset += size;
+	assert(arg->offset < arg->size);
+
+	return 0;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/ANY.h b/libkmod/pkcs7/asn1c-gen/ANY.h
new file mode 100644
index 000000000000..b7d92fa98265
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ANY.h
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef ASN_TYPE_ANY_H
+#define ASN_TYPE_ANY_H
+
+#include <OCTET_STRING.h>	/* Implemented via OCTET STRING type */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ANY {
+	uint8_t *buf;	/* BER-encoded ANY contents */
+	int size;	/* Size of the above buffer */
+
+	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer boundaries */
+} ANY_t;
+
+extern asn_TYPE_descriptor_t asn_DEF_ANY;
+
+asn_struct_free_f ANY_free;
+asn_struct_print_f ANY_print;
+ber_type_decoder_f ANY_decode_ber;
+der_type_encoder_f ANY_encode_der;
+xer_type_encoder_f ANY_encode_xer;
+
+/******************************
+ * Handy conversion routines. *
+ ******************************/
+
+/* Convert another ASN.1 type into the ANY. This implies DER encoding. */
+int ANY_fromType(ANY_t *, asn_TYPE_descriptor_t *td, void *struct_ptr);
+ANY_t *ANY_new_fromType(asn_TYPE_descriptor_t *td, void *struct_ptr);
+
+/* Convert the contents of the ANY type into the specified type. */
+int ANY_to_type(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
+
+#define	ANY_fromBuf(s, buf, size)	OCTET_STRING_fromBuf((s), (buf), (size))
+#define	ANY_new_fromBuf(buf, size)	OCTET_STRING_new_fromBuf(	\
+						&asn_DEF_ANY, (buf), (size))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ASN_TYPE_ANY_H */
diff --git a/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c b/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c
new file mode 100644
index 000000000000..ec2db00c6ce0
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c
@@ -0,0 +1,68 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "AttributeValueAssertion.h"
+
+static asn_TYPE_member_t asn_MBR_AttributeValueAssertion_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct AttributeValueAssertion, attributeType),
+		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
+		0,
+		&asn_DEF_OBJECT_IDENTIFIER,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"attributeType"
+		},
+	{ ATF_OPEN_TYPE | ATF_NOFLAGS, 0, offsetof(struct AttributeValueAssertion, attributeValue),
+		-1 /* Ambiguous tag (ANY?) */,
+		0,
+		&asn_DEF_ANY,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"attributeValue"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_AttributeValueAssertion_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_AttributeValueAssertion_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 } /* attributeType */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_AttributeValueAssertion_specs_1 = {
+	sizeof(struct AttributeValueAssertion),
+	offsetof(struct AttributeValueAssertion, _asn_ctx),
+	asn_MAP_AttributeValueAssertion_tag2el_1,
+	1,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_AttributeValueAssertion = {
+	"AttributeValueAssertion",
+	"AttributeValueAssertion",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_AttributeValueAssertion_tags_1,
+	sizeof(asn_DEF_AttributeValueAssertion_tags_1)
+		/sizeof(asn_DEF_AttributeValueAssertion_tags_1[0]), /* 1 */
+	asn_DEF_AttributeValueAssertion_tags_1,	/* Same as above */
+	sizeof(asn_DEF_AttributeValueAssertion_tags_1)
+		/sizeof(asn_DEF_AttributeValueAssertion_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_AttributeValueAssertion_1,
+	2,	/* Elements count */
+	&asn_SPC_AttributeValueAssertion_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h b/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h
new file mode 100644
index 000000000000..3446d61e89dc
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h
@@ -0,0 +1,40 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_AttributeValueAssertion_H_
+#define	_AttributeValueAssertion_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <OBJECT_IDENTIFIER.h>
+#include <ANY.h>
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* AttributeValueAssertion */
+typedef struct AttributeValueAssertion {
+	OBJECT_IDENTIFIER_t	 attributeType;
+	ANY_t	 attributeValue;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} AttributeValueAssertion_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_AttributeValueAssertion;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _AttributeValueAssertion_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c b/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c
new file mode 100644
index 000000000000..011505b60e05
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c
@@ -0,0 +1,69 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "AuthenticatedAttribute.h"
+
+static asn_TYPE_member_t asn_MBR_AuthenticatedAttribute_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct AuthenticatedAttribute, type),
+		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
+		0,
+		&asn_DEF_OBJECT_IDENTIFIER,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"type"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct AuthenticatedAttribute, values),
+		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
+		0,
+		&asn_DEF_Values,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"values"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_AuthenticatedAttribute_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_AuthenticatedAttribute_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /* type */
+    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 1, 0, 0 } /* values */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_AuthenticatedAttribute_specs_1 = {
+	sizeof(struct AuthenticatedAttribute),
+	offsetof(struct AuthenticatedAttribute, _asn_ctx),
+	asn_MAP_AuthenticatedAttribute_tag2el_1,
+	2,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_AuthenticatedAttribute = {
+	"AuthenticatedAttribute",
+	"AuthenticatedAttribute",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_AuthenticatedAttribute_tags_1,
+	sizeof(asn_DEF_AuthenticatedAttribute_tags_1)
+		/sizeof(asn_DEF_AuthenticatedAttribute_tags_1[0]), /* 1 */
+	asn_DEF_AuthenticatedAttribute_tags_1,	/* Same as above */
+	sizeof(asn_DEF_AuthenticatedAttribute_tags_1)
+		/sizeof(asn_DEF_AuthenticatedAttribute_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_AuthenticatedAttribute_1,
+	2,	/* Elements count */
+	&asn_SPC_AuthenticatedAttribute_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h b/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h
new file mode 100644
index 000000000000..a140afb7f31a
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h
@@ -0,0 +1,40 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_AuthenticatedAttribute_H_
+#define	_AuthenticatedAttribute_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <OBJECT_IDENTIFIER.h>
+#include "Values.h"
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* AuthenticatedAttribute */
+typedef struct AuthenticatedAttribute {
+	OBJECT_IDENTIFIER_t	 type;
+	Values_t	 values;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} AuthenticatedAttribute_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_AuthenticatedAttribute;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _AuthenticatedAttribute_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/BIT_STRING.c b/libkmod/pkcs7/asn1c-gen/BIT_STRING.c
new file mode 100644
index 000000000000..997ff41619e3
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/BIT_STRING.c
@@ -0,0 +1,189 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <BIT_STRING.h>
+#include <asn_internal.h>
+
+/*
+ * BIT STRING basic type description.
+ */
+static const ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
+};
+static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = {
+	sizeof(BIT_STRING_t),
+	offsetof(BIT_STRING_t, _asn_ctx),
+	ASN_OSUBV_BIT
+};
+asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
+	"BIT STRING",
+	"BIT_STRING",
+	OCTET_STRING_free,         /* Implemented in terms of OCTET STRING */
+	BIT_STRING_print,
+	BIT_STRING_constraint,
+	OCTET_STRING_decode_ber,   /* Implemented in terms of OCTET STRING */
+	OCTET_STRING_encode_der,   /* Implemented in terms of OCTET STRING */
+	OCTET_STRING_decode_xer_binary,
+	BIT_STRING_encode_xer,
+	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
+	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
+	0, /* Use generic outmost tag fetcher */
+	asn_DEF_BIT_STRING_tags,
+	sizeof(asn_DEF_BIT_STRING_tags)
+	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
+	asn_DEF_BIT_STRING_tags,	/* Same as above */
+	sizeof(asn_DEF_BIT_STRING_tags)
+	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	&asn_DEF_BIT_STRING_specs
+};
+
+/*
+ * BIT STRING generic constraint.
+ */
+int
+BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
+
+	if(st && st->buf) {
+		if((st->size == 0 && st->bits_unused)
+		|| st->bits_unused < 0 || st->bits_unused > 7) {
+			ASN__CTFAIL(app_key, td, sptr,
+				"%s: invalid padding byte (%s:%d)",
+				td->name, __FILE__, __LINE__);
+			return -1;
+		}
+	} else {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: value not given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+
+	return 0;
+}
+
+static char *_bit_pattern[16] = {
+	"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
+	"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
+};
+
+asn_enc_rval_t
+BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_enc_rval_t er;
+	char scratch[128];
+	char *p = scratch;
+	char *scend = scratch + (sizeof(scratch) - 10);
+	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
+	int xcan = (flags & XER_F_CANONICAL);
+	uint8_t *buf;
+	uint8_t *end;
+
+	if(!st || !st->buf)
+		ASN__ENCODE_FAILED;
+
+	er.encoded = 0;
+
+	buf = st->buf;
+	end = buf + st->size - 1;	/* Last byte is special */
+
+	/*
+	 * Binary dump
+	 */
+	for(; buf < end; buf++) {
+		int v = *buf;
+		int nline = xcan?0:(((buf - st->buf) % 8) == 0);
+		if(p >= scend || nline) {
+			er.encoded += p - scratch;
+			ASN__CALLBACK(scratch, p - scratch);
+			p = scratch;
+			if(nline) ASN__TEXT_INDENT(1, ilevel);
+		}
+		memcpy(p + 0, _bit_pattern[v >> 4], 4);
+		memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
+		p += 8;
+	}
+
+	if(!xcan && ((buf - st->buf) % 8) == 0)
+		ASN__TEXT_INDENT(1, ilevel);
+	er.encoded += p - scratch;
+	ASN__CALLBACK(scratch, p - scratch);
+	p = scratch;
+
+	if(buf == end) {
+		int v = *buf;
+		int ubits = st->bits_unused;
+		int i;
+		for(i = 7; i >= ubits; i--)
+			*p++ = (v & (1 << i)) ? 0x31 : 0x30;
+		er.encoded += p - scratch;
+		ASN__CALLBACK(scratch, p - scratch);
+	}
+
+	if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
+
+	ASN__ENCODED_OK(er);
+cb_failed:
+	ASN__ENCODE_FAILED;
+}
+
+
+/*
+ * BIT STRING specific contents printer.
+ */
+int
+BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	const char * const h2c = "0123456789ABCDEF";
+	char scratch[64];
+	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
+	uint8_t *buf;
+	uint8_t *end;
+	char *p = scratch;
+
+	(void)td;	/* Unused argument */
+
+	if(!st || !st->buf)
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+
+	ilevel++;
+	buf = st->buf;
+	end = buf + st->size;
+
+	/*
+	 * Hexadecimal dump.
+	 */
+	for(; buf < end; buf++) {
+		if((buf - st->buf) % 16 == 0 && (st->size > 16)
+				&& buf != st->buf) {
+			_i_INDENT(1);
+			/* Dump the string */
+			if(cb(scratch, p - scratch, app_key) < 0) return -1;
+			p = scratch;
+		}
+		*p++ = h2c[*buf >> 4];
+		*p++ = h2c[*buf & 0x0F];
+		*p++ = 0x20;
+	}
+
+	if(p > scratch) {
+		p--;	/* Eat the tailing space */
+
+		if((st->size > 16)) {
+			_i_INDENT(1);
+		}
+
+		/* Dump the incomplete 16-bytes row */
+		if(cb(scratch, p - scratch, app_key) < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/BIT_STRING.h b/libkmod/pkcs7/asn1c-gen/BIT_STRING.h
new file mode 100644
index 000000000000..732e878bcad1
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/BIT_STRING.h
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_BIT_STRING_H_
+#define	_BIT_STRING_H_
+
+#include <OCTET_STRING.h>	/* Some help from OCTET STRING */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct BIT_STRING_s {
+	uint8_t *buf;	/* BIT STRING body */
+	int size;	/* Size of the above buffer */
+
+	int bits_unused;/* Unused trailing bits in the last octet (0..7) */
+
+	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer boundaries */
+} BIT_STRING_t;
+
+extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING;
+
+asn_struct_print_f BIT_STRING_print;	/* Human-readable output */
+asn_constr_check_f BIT_STRING_constraint;
+xer_type_encoder_f BIT_STRING_encode_xer;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _BIT_STRING_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/CRLSequence.c b/libkmod/pkcs7/asn1c-gen/CRLSequence.c
new file mode 100644
index 000000000000..555425c270a3
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/CRLSequence.c
@@ -0,0 +1,52 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "CRLSequence.h"
+
+static asn_TYPE_member_t asn_MBR_CRLSequence_1[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_CertificateList,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_CRLSequence_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_CRLSequence_specs_1 = {
+	sizeof(struct CRLSequence),
+	offsetof(struct CRLSequence, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_CRLSequence = {
+	"CRLSequence",
+	"CRLSequence",
+	SEQUENCE_OF_free,
+	SEQUENCE_OF_print,
+	SEQUENCE_OF_constraint,
+	SEQUENCE_OF_decode_ber,
+	SEQUENCE_OF_encode_der,
+	SEQUENCE_OF_decode_xer,
+	SEQUENCE_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_CRLSequence_tags_1,
+	sizeof(asn_DEF_CRLSequence_tags_1)
+		/sizeof(asn_DEF_CRLSequence_tags_1[0]), /* 1 */
+	asn_DEF_CRLSequence_tags_1,	/* Same as above */
+	sizeof(asn_DEF_CRLSequence_tags_1)
+		/sizeof(asn_DEF_CRLSequence_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_CRLSequence_1,
+	1,	/* Single element */
+	&asn_SPC_CRLSequence_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/CRLSequence.h b/libkmod/pkcs7/asn1c-gen/CRLSequence.h
new file mode 100644
index 000000000000..8e64d30642f8
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/CRLSequence.h
@@ -0,0 +1,44 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_CRLSequence_H_
+#define	_CRLSequence_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <asn_SEQUENCE_OF.h>
+#include <constr_SEQUENCE_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct CertificateList;
+
+/* CRLSequence */
+typedef struct CRLSequence {
+	A_SEQUENCE_OF(struct CertificateList) list;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} CRLSequence_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_CRLSequence;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "CertificateList.h"
+
+#endif	/* _CRLSequence_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/Certificate.c b/libkmod/pkcs7/asn1c-gen/Certificate.c
new file mode 100644
index 000000000000..2216797c4447
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Certificate.c
@@ -0,0 +1,104 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "Certificate.h"
+
+int
+Certificate_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	/* Replace with underlying type checker */
+	td->check_constraints = asn_DEF_ANY.check_constraints;
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+/*
+ * This type is implemented using ANY,
+ * so here we adjust the DEF accordingly.
+ */
+static void
+Certificate_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
+	td->free_struct    = asn_DEF_ANY.free_struct;
+	td->print_struct   = asn_DEF_ANY.print_struct;
+	td->check_constraints = asn_DEF_ANY.check_constraints;
+	td->ber_decoder    = asn_DEF_ANY.ber_decoder;
+	td->der_encoder    = asn_DEF_ANY.der_encoder;
+	td->xer_decoder    = asn_DEF_ANY.xer_decoder;
+	td->xer_encoder    = asn_DEF_ANY.xer_encoder;
+	td->uper_decoder   = asn_DEF_ANY.uper_decoder;
+	td->uper_encoder   = asn_DEF_ANY.uper_encoder;
+	if(!td->per_constraints)
+		td->per_constraints = asn_DEF_ANY.per_constraints;
+	td->elements       = asn_DEF_ANY.elements;
+	td->elements_count = asn_DEF_ANY.elements_count;
+	td->specifics      = asn_DEF_ANY.specifics;
+}
+
+void
+Certificate_free(asn_TYPE_descriptor_t *td,
+		void *struct_ptr, int contents_only) {
+	Certificate_1_inherit_TYPE_descriptor(td);
+	td->free_struct(td, struct_ptr, contents_only);
+}
+
+int
+Certificate_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
+		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
+	Certificate_1_inherit_TYPE_descriptor(td);
+	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
+}
+
+asn_dec_rval_t
+Certificate_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const void *bufptr, size_t size, int tag_mode) {
+	Certificate_1_inherit_TYPE_descriptor(td);
+	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
+}
+
+asn_enc_rval_t
+Certificate_encode_der(asn_TYPE_descriptor_t *td,
+		void *structure, int tag_mode, ber_tlv_tag_t tag,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	Certificate_1_inherit_TYPE_descriptor(td);
+	return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
+}
+
+asn_dec_rval_t
+Certificate_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const char *opt_mname, const void *bufptr, size_t size) {
+	Certificate_1_inherit_TYPE_descriptor(td);
+	return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
+}
+
+asn_enc_rval_t
+Certificate_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
+		int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	Certificate_1_inherit_TYPE_descriptor(td);
+	return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
+}
+
+asn_TYPE_descriptor_t asn_DEF_Certificate = {
+	"Certificate",
+	"Certificate",
+	Certificate_free,
+	Certificate_print,
+	Certificate_constraint,
+	Certificate_decode_ber,
+	Certificate_encode_der,
+	Certificate_decode_xer,
+	Certificate_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/Certificate.h b/libkmod/pkcs7/asn1c-gen/Certificate.h
new file mode 100644
index 000000000000..e0229c021e16
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Certificate.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_Certificate_H_
+#define	_Certificate_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <ANY.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Certificate */
+typedef ANY_t	 Certificate_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_Certificate;
+asn_struct_free_f Certificate_free;
+asn_struct_print_f Certificate_print;
+asn_constr_check_f Certificate_constraint;
+ber_type_decoder_f Certificate_decode_ber;
+der_type_encoder_f Certificate_encode_der;
+xer_type_decoder_f Certificate_decode_xer;
+xer_type_encoder_f Certificate_encode_xer;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _Certificate_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/CertificateList.c b/libkmod/pkcs7/asn1c-gen/CertificateList.c
new file mode 100644
index 000000000000..f9a2bd2a1b86
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/CertificateList.c
@@ -0,0 +1,52 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "CertificateList.h"
+
+static asn_TYPE_member_t asn_MBR_CertificateList_1[] = {
+	{ ATF_OPEN_TYPE | ATF_POINTER, 0, 0,
+		-1 /* Ambiguous tag (ANY?) */,
+		0,
+		&asn_DEF_Certificate,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_CertificateList_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_CertificateList_specs_1 = {
+	sizeof(struct CertificateList),
+	offsetof(struct CertificateList, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_CertificateList = {
+	"CertificateList",
+	"CertificateList",
+	SEQUENCE_OF_free,
+	SEQUENCE_OF_print,
+	SEQUENCE_OF_constraint,
+	SEQUENCE_OF_decode_ber,
+	SEQUENCE_OF_encode_der,
+	SEQUENCE_OF_decode_xer,
+	SEQUENCE_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_CertificateList_tags_1,
+	sizeof(asn_DEF_CertificateList_tags_1)
+		/sizeof(asn_DEF_CertificateList_tags_1[0]), /* 1 */
+	asn_DEF_CertificateList_tags_1,	/* Same as above */
+	sizeof(asn_DEF_CertificateList_tags_1)
+		/sizeof(asn_DEF_CertificateList_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_CertificateList_1,
+	1,	/* Single element */
+	&asn_SPC_CertificateList_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/CertificateList.h b/libkmod/pkcs7/asn1c-gen/CertificateList.h
new file mode 100644
index 000000000000..b391f4dfa45d
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/CertificateList.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_CertificateList_H_
+#define	_CertificateList_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include "Certificate.h"
+#include <asn_SEQUENCE_OF.h>
+#include <constr_SEQUENCE_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* CertificateList */
+typedef struct CertificateList {
+	A_SEQUENCE_OF(Certificate_t) list;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} CertificateList_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_CertificateList;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _CertificateList_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c b/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c
new file mode 100644
index 000000000000..1d4c387cec05
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c
@@ -0,0 +1,52 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "CertificateRevocationLists.h"
+
+static asn_TYPE_member_t asn_MBR_CertificateRevocationLists_1[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_CertificateList,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_CertificateRevocationLists_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_CertificateRevocationLists_specs_1 = {
+	sizeof(struct CertificateRevocationLists),
+	offsetof(struct CertificateRevocationLists, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_CertificateRevocationLists = {
+	"CertificateRevocationLists",
+	"CertificateRevocationLists",
+	SET_OF_free,
+	SET_OF_print,
+	SET_OF_constraint,
+	SET_OF_decode_ber,
+	SET_OF_encode_der,
+	SET_OF_decode_xer,
+	SET_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_CertificateRevocationLists_tags_1,
+	sizeof(asn_DEF_CertificateRevocationLists_tags_1)
+		/sizeof(asn_DEF_CertificateRevocationLists_tags_1[0]), /* 1 */
+	asn_DEF_CertificateRevocationLists_tags_1,	/* Same as above */
+	sizeof(asn_DEF_CertificateRevocationLists_tags_1)
+		/sizeof(asn_DEF_CertificateRevocationLists_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_CertificateRevocationLists_1,
+	1,	/* Single element */
+	&asn_SPC_CertificateRevocationLists_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h b/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h
new file mode 100644
index 000000000000..064deea9d3e3
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h
@@ -0,0 +1,44 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_CertificateRevocationLists_H_
+#define	_CertificateRevocationLists_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <asn_SET_OF.h>
+#include <constr_SET_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct CertificateList;
+
+/* CertificateRevocationLists */
+typedef struct CertificateRevocationLists {
+	A_SET_OF(struct CertificateList) list;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} CertificateRevocationLists_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_CertificateRevocationLists;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "CertificateList.h"
+
+#endif	/* _CertificateRevocationLists_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c b/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c
new file mode 100644
index 000000000000..c0cb62523f43
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c
@@ -0,0 +1,109 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "CertificateSerialNumber.h"
+
+int
+CertificateSerialNumber_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	/* Replace with underlying type checker */
+	td->check_constraints = asn_DEF_INTEGER.check_constraints;
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+/*
+ * This type is implemented using INTEGER,
+ * so here we adjust the DEF accordingly.
+ */
+static void
+CertificateSerialNumber_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
+	td->free_struct    = asn_DEF_INTEGER.free_struct;
+	td->print_struct   = asn_DEF_INTEGER.print_struct;
+	td->check_constraints = asn_DEF_INTEGER.check_constraints;
+	td->ber_decoder    = asn_DEF_INTEGER.ber_decoder;
+	td->der_encoder    = asn_DEF_INTEGER.der_encoder;
+	td->xer_decoder    = asn_DEF_INTEGER.xer_decoder;
+	td->xer_encoder    = asn_DEF_INTEGER.xer_encoder;
+	td->uper_decoder   = asn_DEF_INTEGER.uper_decoder;
+	td->uper_encoder   = asn_DEF_INTEGER.uper_encoder;
+	if(!td->per_constraints)
+		td->per_constraints = asn_DEF_INTEGER.per_constraints;
+	td->elements       = asn_DEF_INTEGER.elements;
+	td->elements_count = asn_DEF_INTEGER.elements_count;
+	td->specifics      = asn_DEF_INTEGER.specifics;
+}
+
+void
+CertificateSerialNumber_free(asn_TYPE_descriptor_t *td,
+		void *struct_ptr, int contents_only) {
+	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
+	td->free_struct(td, struct_ptr, contents_only);
+}
+
+int
+CertificateSerialNumber_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
+		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
+	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
+	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
+}
+
+asn_dec_rval_t
+CertificateSerialNumber_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const void *bufptr, size_t size, int tag_mode) {
+	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
+	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
+}
+
+asn_enc_rval_t
+CertificateSerialNumber_encode_der(asn_TYPE_descriptor_t *td,
+		void *structure, int tag_mode, ber_tlv_tag_t tag,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
+	return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
+}
+
+asn_dec_rval_t
+CertificateSerialNumber_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const char *opt_mname, const void *bufptr, size_t size) {
+	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
+	return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
+}
+
+asn_enc_rval_t
+CertificateSerialNumber_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
+		int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
+	return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
+}
+
+static const ber_tlv_tag_t asn_DEF_CertificateSerialNumber_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_CertificateSerialNumber = {
+	"CertificateSerialNumber",
+	"CertificateSerialNumber",
+	CertificateSerialNumber_free,
+	CertificateSerialNumber_print,
+	CertificateSerialNumber_constraint,
+	CertificateSerialNumber_decode_ber,
+	CertificateSerialNumber_encode_der,
+	CertificateSerialNumber_decode_xer,
+	CertificateSerialNumber_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_CertificateSerialNumber_tags_1,
+	sizeof(asn_DEF_CertificateSerialNumber_tags_1)
+		/sizeof(asn_DEF_CertificateSerialNumber_tags_1[0]), /* 1 */
+	asn_DEF_CertificateSerialNumber_tags_1,	/* Same as above */
+	sizeof(asn_DEF_CertificateSerialNumber_tags_1)
+		/sizeof(asn_DEF_CertificateSerialNumber_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h b/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h
new file mode 100644
index 000000000000..b82390d40491
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_CertificateSerialNumber_H_
+#define	_CertificateSerialNumber_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* CertificateSerialNumber */
+typedef INTEGER_t	 CertificateSerialNumber_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_CertificateSerialNumber;
+asn_struct_free_f CertificateSerialNumber_free;
+asn_struct_print_f CertificateSerialNumber_print;
+asn_constr_check_f CertificateSerialNumber_constraint;
+ber_type_decoder_f CertificateSerialNumber_decode_ber;
+der_type_encoder_f CertificateSerialNumber_encode_der;
+xer_type_decoder_f CertificateSerialNumber_decode_xer;
+xer_type_encoder_f CertificateSerialNumber_encode_xer;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _CertificateSerialNumber_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/Certificates.c b/libkmod/pkcs7/asn1c-gen/Certificates.c
new file mode 100644
index 000000000000..46d885299683
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Certificates.c
@@ -0,0 +1,52 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "Certificates.h"
+
+static asn_TYPE_member_t asn_MBR_Certificates_1[] = {
+	{ ATF_OPEN_TYPE | ATF_POINTER, 0, 0,
+		-1 /* Ambiguous tag (ANY?) */,
+		0,
+		&asn_DEF_Certificate,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_Certificates_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_Certificates_specs_1 = {
+	sizeof(struct Certificates),
+	offsetof(struct Certificates, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_Certificates = {
+	"Certificates",
+	"Certificates",
+	SEQUENCE_OF_free,
+	SEQUENCE_OF_print,
+	SEQUENCE_OF_constraint,
+	SEQUENCE_OF_decode_ber,
+	SEQUENCE_OF_encode_der,
+	SEQUENCE_OF_decode_xer,
+	SEQUENCE_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_Certificates_tags_1,
+	sizeof(asn_DEF_Certificates_tags_1)
+		/sizeof(asn_DEF_Certificates_tags_1[0]), /* 1 */
+	asn_DEF_Certificates_tags_1,	/* Same as above */
+	sizeof(asn_DEF_Certificates_tags_1)
+		/sizeof(asn_DEF_Certificates_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_Certificates_1,
+	1,	/* Single element */
+	&asn_SPC_Certificates_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/Certificates.h b/libkmod/pkcs7/asn1c-gen/Certificates.h
new file mode 100644
index 000000000000..9ba77c12015e
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Certificates.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_Certificates_H_
+#define	_Certificates_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include "Certificate.h"
+#include <asn_SEQUENCE_OF.h>
+#include <constr_SEQUENCE_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Certificates */
+typedef struct Certificates {
+	A_SEQUENCE_OF(Certificate_t) list;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} Certificates_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_Certificates;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _Certificates_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/ContentInfo.c b/libkmod/pkcs7/asn1c-gen/ContentInfo.c
new file mode 100644
index 000000000000..ba7a2f898ce2
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ContentInfo.c
@@ -0,0 +1,69 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "ContentInfo.h"
+
+static asn_TYPE_member_t asn_MBR_ContentInfo_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct ContentInfo, contentType),
+		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
+		0,
+		&asn_DEF_ContentType,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"contentType"
+		},
+	{ ATF_POINTER, 1, offsetof(struct ContentInfo, content),
+		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+		+1,	/* EXPLICIT tag at current level */
+		&asn_DEF_Data,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"content"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_ContentInfo_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_ContentInfo_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /* contentType */
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, 0, 0 } /* content */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_ContentInfo_specs_1 = {
+	sizeof(struct ContentInfo),
+	offsetof(struct ContentInfo, _asn_ctx),
+	asn_MAP_ContentInfo_tag2el_1,
+	2,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_ContentInfo = {
+	"ContentInfo",
+	"ContentInfo",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_ContentInfo_tags_1,
+	sizeof(asn_DEF_ContentInfo_tags_1)
+		/sizeof(asn_DEF_ContentInfo_tags_1[0]), /* 1 */
+	asn_DEF_ContentInfo_tags_1,	/* Same as above */
+	sizeof(asn_DEF_ContentInfo_tags_1)
+		/sizeof(asn_DEF_ContentInfo_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_ContentInfo_1,
+	2,	/* Elements count */
+	&asn_SPC_ContentInfo_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/ContentInfo.h b/libkmod/pkcs7/asn1c-gen/ContentInfo.h
new file mode 100644
index 000000000000..c0d2f8a2d6bb
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ContentInfo.h
@@ -0,0 +1,40 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_ContentInfo_H_
+#define	_ContentInfo_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include "ContentType.h"
+#include "Data.h"
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ContentInfo */
+typedef struct ContentInfo {
+	ContentType_t	 contentType;
+	Data_t	*content	/* OPTIONAL */;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} ContentInfo_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_ContentInfo;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _ContentInfo_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/ContentType.c b/libkmod/pkcs7/asn1c-gen/ContentType.c
new file mode 100644
index 000000000000..c7d4b19973d6
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ContentType.c
@@ -0,0 +1,109 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "ContentType.h"
+
+int
+ContentType_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	/* Replace with underlying type checker */
+	td->check_constraints = asn_DEF_OBJECT_IDENTIFIER.check_constraints;
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+/*
+ * This type is implemented using OBJECT_IDENTIFIER,
+ * so here we adjust the DEF accordingly.
+ */
+static void
+ContentType_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
+	td->free_struct    = asn_DEF_OBJECT_IDENTIFIER.free_struct;
+	td->print_struct   = asn_DEF_OBJECT_IDENTIFIER.print_struct;
+	td->check_constraints = asn_DEF_OBJECT_IDENTIFIER.check_constraints;
+	td->ber_decoder    = asn_DEF_OBJECT_IDENTIFIER.ber_decoder;
+	td->der_encoder    = asn_DEF_OBJECT_IDENTIFIER.der_encoder;
+	td->xer_decoder    = asn_DEF_OBJECT_IDENTIFIER.xer_decoder;
+	td->xer_encoder    = asn_DEF_OBJECT_IDENTIFIER.xer_encoder;
+	td->uper_decoder   = asn_DEF_OBJECT_IDENTIFIER.uper_decoder;
+	td->uper_encoder   = asn_DEF_OBJECT_IDENTIFIER.uper_encoder;
+	if(!td->per_constraints)
+		td->per_constraints = asn_DEF_OBJECT_IDENTIFIER.per_constraints;
+	td->elements       = asn_DEF_OBJECT_IDENTIFIER.elements;
+	td->elements_count = asn_DEF_OBJECT_IDENTIFIER.elements_count;
+	td->specifics      = asn_DEF_OBJECT_IDENTIFIER.specifics;
+}
+
+void
+ContentType_free(asn_TYPE_descriptor_t *td,
+		void *struct_ptr, int contents_only) {
+	ContentType_1_inherit_TYPE_descriptor(td);
+	td->free_struct(td, struct_ptr, contents_only);
+}
+
+int
+ContentType_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
+		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
+	ContentType_1_inherit_TYPE_descriptor(td);
+	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
+}
+
+asn_dec_rval_t
+ContentType_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const void *bufptr, size_t size, int tag_mode) {
+	ContentType_1_inherit_TYPE_descriptor(td);
+	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
+}
+
+asn_enc_rval_t
+ContentType_encode_der(asn_TYPE_descriptor_t *td,
+		void *structure, int tag_mode, ber_tlv_tag_t tag,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	ContentType_1_inherit_TYPE_descriptor(td);
+	return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
+}
+
+asn_dec_rval_t
+ContentType_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const char *opt_mname, const void *bufptr, size_t size) {
+	ContentType_1_inherit_TYPE_descriptor(td);
+	return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
+}
+
+asn_enc_rval_t
+ContentType_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
+		int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	ContentType_1_inherit_TYPE_descriptor(td);
+	return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
+}
+
+static const ber_tlv_tag_t asn_DEF_ContentType_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (6 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_ContentType = {
+	"ContentType",
+	"ContentType",
+	ContentType_free,
+	ContentType_print,
+	ContentType_constraint,
+	ContentType_decode_ber,
+	ContentType_encode_der,
+	ContentType_decode_xer,
+	ContentType_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_ContentType_tags_1,
+	sizeof(asn_DEF_ContentType_tags_1)
+		/sizeof(asn_DEF_ContentType_tags_1[0]), /* 1 */
+	asn_DEF_ContentType_tags_1,	/* Same as above */
+	sizeof(asn_DEF_ContentType_tags_1)
+		/sizeof(asn_DEF_ContentType_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/ContentType.h b/libkmod/pkcs7/asn1c-gen/ContentType.h
new file mode 100644
index 000000000000..fd47de6f6c7f
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ContentType.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_ContentType_H_
+#define	_ContentType_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <OBJECT_IDENTIFIER.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ContentType */
+typedef OBJECT_IDENTIFIER_t	 ContentType_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_ContentType;
+asn_struct_free_f ContentType_free;
+asn_struct_print_f ContentType_print;
+asn_constr_check_f ContentType_constraint;
+ber_type_decoder_f ContentType_decode_ber;
+der_type_encoder_f ContentType_encode_der;
+xer_type_decoder_f ContentType_decode_xer;
+xer_type_encoder_f ContentType_encode_xer;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _ContentType_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/Data.c b/libkmod/pkcs7/asn1c-gen/Data.c
new file mode 100644
index 000000000000..d158bf5f30fc
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Data.c
@@ -0,0 +1,104 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "Data.h"
+
+int
+Data_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	/* Replace with underlying type checker */
+	td->check_constraints = asn_DEF_ANY.check_constraints;
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+/*
+ * This type is implemented using ANY,
+ * so here we adjust the DEF accordingly.
+ */
+static void
+Data_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
+	td->free_struct    = asn_DEF_ANY.free_struct;
+	td->print_struct   = asn_DEF_ANY.print_struct;
+	td->check_constraints = asn_DEF_ANY.check_constraints;
+	td->ber_decoder    = asn_DEF_ANY.ber_decoder;
+	td->der_encoder    = asn_DEF_ANY.der_encoder;
+	td->xer_decoder    = asn_DEF_ANY.xer_decoder;
+	td->xer_encoder    = asn_DEF_ANY.xer_encoder;
+	td->uper_decoder   = asn_DEF_ANY.uper_decoder;
+	td->uper_encoder   = asn_DEF_ANY.uper_encoder;
+	if(!td->per_constraints)
+		td->per_constraints = asn_DEF_ANY.per_constraints;
+	td->elements       = asn_DEF_ANY.elements;
+	td->elements_count = asn_DEF_ANY.elements_count;
+	td->specifics      = asn_DEF_ANY.specifics;
+}
+
+void
+Data_free(asn_TYPE_descriptor_t *td,
+		void *struct_ptr, int contents_only) {
+	Data_1_inherit_TYPE_descriptor(td);
+	td->free_struct(td, struct_ptr, contents_only);
+}
+
+int
+Data_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
+		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
+	Data_1_inherit_TYPE_descriptor(td);
+	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
+}
+
+asn_dec_rval_t
+Data_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const void *bufptr, size_t size, int tag_mode) {
+	Data_1_inherit_TYPE_descriptor(td);
+	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
+}
+
+asn_enc_rval_t
+Data_encode_der(asn_TYPE_descriptor_t *td,
+		void *structure, int tag_mode, ber_tlv_tag_t tag,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	Data_1_inherit_TYPE_descriptor(td);
+	return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
+}
+
+asn_dec_rval_t
+Data_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const char *opt_mname, const void *bufptr, size_t size) {
+	Data_1_inherit_TYPE_descriptor(td);
+	return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
+}
+
+asn_enc_rval_t
+Data_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
+		int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	Data_1_inherit_TYPE_descriptor(td);
+	return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
+}
+
+asn_TYPE_descriptor_t asn_DEF_Data = {
+	"Data",
+	"Data",
+	Data_free,
+	Data_print,
+	Data_constraint,
+	Data_decode_ber,
+	Data_encode_der,
+	Data_decode_xer,
+	Data_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/Data.h b/libkmod/pkcs7/asn1c-gen/Data.h
new file mode 100644
index 000000000000..314729dbdec3
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Data.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_Data_H_
+#define	_Data_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <ANY.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Data */
+typedef ANY_t	 Data_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_Data;
+asn_struct_free_f Data_free;
+asn_struct_print_f Data_print;
+asn_constr_check_f Data_constraint;
+ber_type_decoder_f Data_decode_ber;
+der_type_encoder_f Data_encode_der;
+xer_type_decoder_f Data_decode_xer;
+xer_type_encoder_f Data_encode_xer;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _Data_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c
new file mode 100644
index 000000000000..fc56ff9337ce
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c
@@ -0,0 +1,68 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "DigestAlgorithmIdentifier.h"
+
+static asn_TYPE_member_t asn_MBR_DigestAlgorithmIdentifier_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct DigestAlgorithmIdentifier, algorithm),
+		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
+		0,
+		&asn_DEF_OBJECT_IDENTIFIER,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"algorithm"
+		},
+	{ ATF_OPEN_TYPE | ATF_POINTER, 1, offsetof(struct DigestAlgorithmIdentifier, parameters),
+		-1 /* Ambiguous tag (ANY?) */,
+		0,
+		&asn_DEF_ANY,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"parameters"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_DigestAlgorithmIdentifier_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_DigestAlgorithmIdentifier_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 } /* algorithm */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_DigestAlgorithmIdentifier_specs_1 = {
+	sizeof(struct DigestAlgorithmIdentifier),
+	offsetof(struct DigestAlgorithmIdentifier, _asn_ctx),
+	asn_MAP_DigestAlgorithmIdentifier_tag2el_1,
+	1,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_DigestAlgorithmIdentifier = {
+	"DigestAlgorithmIdentifier",
+	"DigestAlgorithmIdentifier",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_DigestAlgorithmIdentifier_tags_1,
+	sizeof(asn_DEF_DigestAlgorithmIdentifier_tags_1)
+		/sizeof(asn_DEF_DigestAlgorithmIdentifier_tags_1[0]), /* 1 */
+	asn_DEF_DigestAlgorithmIdentifier_tags_1,	/* Same as above */
+	sizeof(asn_DEF_DigestAlgorithmIdentifier_tags_1)
+		/sizeof(asn_DEF_DigestAlgorithmIdentifier_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_DigestAlgorithmIdentifier_1,
+	2,	/* Elements count */
+	&asn_SPC_DigestAlgorithmIdentifier_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h
new file mode 100644
index 000000000000..92e726c2922e
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h
@@ -0,0 +1,40 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_DigestAlgorithmIdentifier_H_
+#define	_DigestAlgorithmIdentifier_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <OBJECT_IDENTIFIER.h>
+#include <ANY.h>
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DigestAlgorithmIdentifier */
+typedef struct DigestAlgorithmIdentifier {
+	OBJECT_IDENTIFIER_t	 algorithm;
+	ANY_t	*parameters	/* OPTIONAL */;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} DigestAlgorithmIdentifier_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_DigestAlgorithmIdentifier;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _DigestAlgorithmIdentifier_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c
new file mode 100644
index 000000000000..3b0ffd27c891
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c
@@ -0,0 +1,153 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "DigestAlgorithmIdentifiers.h"
+
+static asn_TYPE_member_t asn_MBR_daSet_2[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_DigestAlgorithmIdentifier,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_daSet_tags_2[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_daSet_specs_2 = {
+	sizeof(struct daSet),
+	offsetof(struct daSet, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_daSet_2 = {
+	"daSet",
+	"daSet",
+	SET_OF_free,
+	SET_OF_print,
+	SET_OF_constraint,
+	SET_OF_decode_ber,
+	SET_OF_encode_der,
+	SET_OF_decode_xer,
+	SET_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_daSet_tags_2,
+	sizeof(asn_DEF_daSet_tags_2)
+		/sizeof(asn_DEF_daSet_tags_2[0]), /* 1 */
+	asn_DEF_daSet_tags_2,	/* Same as above */
+	sizeof(asn_DEF_daSet_tags_2)
+		/sizeof(asn_DEF_daSet_tags_2[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_daSet_2,
+	1,	/* Single element */
+	&asn_SPC_daSet_specs_2	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_daSequence_4[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_DigestAlgorithmIdentifier,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_daSequence_tags_4[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_daSequence_specs_4 = {
+	sizeof(struct daSequence),
+	offsetof(struct daSequence, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_daSequence_4 = {
+	"daSequence",
+	"daSequence",
+	SEQUENCE_OF_free,
+	SEQUENCE_OF_print,
+	SEQUENCE_OF_constraint,
+	SEQUENCE_OF_decode_ber,
+	SEQUENCE_OF_encode_der,
+	SEQUENCE_OF_decode_xer,
+	SEQUENCE_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_daSequence_tags_4,
+	sizeof(asn_DEF_daSequence_tags_4)
+		/sizeof(asn_DEF_daSequence_tags_4[0]), /* 1 */
+	asn_DEF_daSequence_tags_4,	/* Same as above */
+	sizeof(asn_DEF_daSequence_tags_4)
+		/sizeof(asn_DEF_daSequence_tags_4[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_daSequence_4,
+	1,	/* Single element */
+	&asn_SPC_daSequence_specs_4	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_DigestAlgorithmIdentifiers_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct DigestAlgorithmIdentifiers, choice.daSet),
+		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
+		0,
+		&asn_DEF_daSet_2,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"daSet"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct DigestAlgorithmIdentifiers, choice.daSequence),
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_daSequence_4,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"daSequence"
+		},
+};
+static const asn_TYPE_tag2member_t asn_MAP_DigestAlgorithmIdentifiers_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 0 }, /* daSequence */
+    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 0, 0, 0 } /* daSet */
+};
+static asn_CHOICE_specifics_t asn_SPC_DigestAlgorithmIdentifiers_specs_1 = {
+	sizeof(struct DigestAlgorithmIdentifiers),
+	offsetof(struct DigestAlgorithmIdentifiers, _asn_ctx),
+	offsetof(struct DigestAlgorithmIdentifiers, present),
+	sizeof(((struct DigestAlgorithmIdentifiers *)0)->present),
+	asn_MAP_DigestAlgorithmIdentifiers_tag2el_1,
+	2,	/* Count of tags in the map */
+	0,
+	-1	/* Extensions start */
+};
+asn_TYPE_descriptor_t asn_DEF_DigestAlgorithmIdentifiers = {
+	"DigestAlgorithmIdentifiers",
+	"DigestAlgorithmIdentifiers",
+	CHOICE_free,
+	CHOICE_print,
+	CHOICE_constraint,
+	CHOICE_decode_ber,
+	CHOICE_encode_der,
+	CHOICE_decode_xer,
+	CHOICE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	CHOICE_outmost_tag,
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	0,	/* No PER visible constraints */
+	asn_MBR_DigestAlgorithmIdentifiers_1,
+	2,	/* Elements count */
+	&asn_SPC_DigestAlgorithmIdentifiers_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h
new file mode 100644
index 000000000000..dc90d321db1a
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h
@@ -0,0 +1,68 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_DigestAlgorithmIdentifiers_H_
+#define	_DigestAlgorithmIdentifiers_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <asn_SET_OF.h>
+#include <constr_SET_OF.h>
+#include <asn_SEQUENCE_OF.h>
+#include <constr_SEQUENCE_OF.h>
+#include <constr_CHOICE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Dependencies */
+typedef enum DigestAlgorithmIdentifiers_PR {
+	DigestAlgorithmIdentifiers_PR_NOTHING,	/* No components present */
+	DigestAlgorithmIdentifiers_PR_daSet,
+	DigestAlgorithmIdentifiers_PR_daSequence
+} DigestAlgorithmIdentifiers_PR;
+
+/* Forward declarations */
+struct DigestAlgorithmIdentifier;
+
+/* DigestAlgorithmIdentifiers */
+typedef struct DigestAlgorithmIdentifiers {
+	DigestAlgorithmIdentifiers_PR present;
+	union DigestAlgorithmIdentifiers_u {
+		struct daSet {
+			A_SET_OF(struct DigestAlgorithmIdentifier) list;
+			
+			/* Context for parsing across buffer boundaries */
+			asn_struct_ctx_t _asn_ctx;
+		} daSet;
+		struct daSequence {
+			A_SEQUENCE_OF(struct DigestAlgorithmIdentifier) list;
+			
+			/* Context for parsing across buffer boundaries */
+			asn_struct_ctx_t _asn_ctx;
+		} daSequence;
+	} choice;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} DigestAlgorithmIdentifiers_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_DigestAlgorithmIdentifiers;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "DigestAlgorithmIdentifier.h"
+
+#endif	/* _DigestAlgorithmIdentifiers_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c b/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c
new file mode 100644
index 000000000000..bccf7fe4677e
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c
@@ -0,0 +1,68 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "DigestEncryptionAlgorithmIdentifier.h"
+
+static asn_TYPE_member_t asn_MBR_DigestEncryptionAlgorithmIdentifier_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct DigestEncryptionAlgorithmIdentifier, algorithm),
+		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
+		0,
+		&asn_DEF_OBJECT_IDENTIFIER,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"algorithm"
+		},
+	{ ATF_OPEN_TYPE | ATF_POINTER, 1, offsetof(struct DigestEncryptionAlgorithmIdentifier, parameters),
+		-1 /* Ambiguous tag (ANY?) */,
+		0,
+		&asn_DEF_ANY,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"parameters"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_DigestEncryptionAlgorithmIdentifier_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 } /* algorithm */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_DigestEncryptionAlgorithmIdentifier_specs_1 = {
+	sizeof(struct DigestEncryptionAlgorithmIdentifier),
+	offsetof(struct DigestEncryptionAlgorithmIdentifier, _asn_ctx),
+	asn_MAP_DigestEncryptionAlgorithmIdentifier_tag2el_1,
+	1,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_DigestEncryptionAlgorithmIdentifier = {
+	"DigestEncryptionAlgorithmIdentifier",
+	"DigestEncryptionAlgorithmIdentifier",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1,
+	sizeof(asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1)
+		/sizeof(asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1[0]), /* 1 */
+	asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1,	/* Same as above */
+	sizeof(asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1)
+		/sizeof(asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_DigestEncryptionAlgorithmIdentifier_1,
+	2,	/* Elements count */
+	&asn_SPC_DigestEncryptionAlgorithmIdentifier_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h b/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h
new file mode 100644
index 000000000000..d06354b07a75
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h
@@ -0,0 +1,40 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_DigestEncryptionAlgorithmIdentifier_H_
+#define	_DigestEncryptionAlgorithmIdentifier_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <OBJECT_IDENTIFIER.h>
+#include <ANY.h>
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DigestEncryptionAlgorithmIdentifier */
+typedef struct DigestEncryptionAlgorithmIdentifier {
+	OBJECT_IDENTIFIER_t	 algorithm;
+	ANY_t	*parameters	/* OPTIONAL */;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} DigestEncryptionAlgorithmIdentifier_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_DigestEncryptionAlgorithmIdentifier;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _DigestEncryptionAlgorithmIdentifier_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/EncryptedDigest.c b/libkmod/pkcs7/asn1c-gen/EncryptedDigest.c
new file mode 100644
index 000000000000..37a36e4ee3ed
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/EncryptedDigest.c
@@ -0,0 +1,109 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "EncryptedDigest.h"
+
+int
+EncryptedDigest_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	/* Replace with underlying type checker */
+	td->check_constraints = asn_DEF_OCTET_STRING.check_constraints;
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+/*
+ * This type is implemented using OCTET_STRING,
+ * so here we adjust the DEF accordingly.
+ */
+static void
+EncryptedDigest_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
+	td->free_struct    = asn_DEF_OCTET_STRING.free_struct;
+	td->print_struct   = asn_DEF_OCTET_STRING.print_struct;
+	td->check_constraints = asn_DEF_OCTET_STRING.check_constraints;
+	td->ber_decoder    = asn_DEF_OCTET_STRING.ber_decoder;
+	td->der_encoder    = asn_DEF_OCTET_STRING.der_encoder;
+	td->xer_decoder    = asn_DEF_OCTET_STRING.xer_decoder;
+	td->xer_encoder    = asn_DEF_OCTET_STRING.xer_encoder;
+	td->uper_decoder   = asn_DEF_OCTET_STRING.uper_decoder;
+	td->uper_encoder   = asn_DEF_OCTET_STRING.uper_encoder;
+	if(!td->per_constraints)
+		td->per_constraints = asn_DEF_OCTET_STRING.per_constraints;
+	td->elements       = asn_DEF_OCTET_STRING.elements;
+	td->elements_count = asn_DEF_OCTET_STRING.elements_count;
+	td->specifics      = asn_DEF_OCTET_STRING.specifics;
+}
+
+void
+EncryptedDigest_free(asn_TYPE_descriptor_t *td,
+		void *struct_ptr, int contents_only) {
+	EncryptedDigest_1_inherit_TYPE_descriptor(td);
+	td->free_struct(td, struct_ptr, contents_only);
+}
+
+int
+EncryptedDigest_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
+		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
+	EncryptedDigest_1_inherit_TYPE_descriptor(td);
+	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
+}
+
+asn_dec_rval_t
+EncryptedDigest_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const void *bufptr, size_t size, int tag_mode) {
+	EncryptedDigest_1_inherit_TYPE_descriptor(td);
+	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
+}
+
+asn_enc_rval_t
+EncryptedDigest_encode_der(asn_TYPE_descriptor_t *td,
+		void *structure, int tag_mode, ber_tlv_tag_t tag,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	EncryptedDigest_1_inherit_TYPE_descriptor(td);
+	return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
+}
+
+asn_dec_rval_t
+EncryptedDigest_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const char *opt_mname, const void *bufptr, size_t size) {
+	EncryptedDigest_1_inherit_TYPE_descriptor(td);
+	return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
+}
+
+asn_enc_rval_t
+EncryptedDigest_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
+		int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	EncryptedDigest_1_inherit_TYPE_descriptor(td);
+	return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
+}
+
+static const ber_tlv_tag_t asn_DEF_EncryptedDigest_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_EncryptedDigest = {
+	"EncryptedDigest",
+	"EncryptedDigest",
+	EncryptedDigest_free,
+	EncryptedDigest_print,
+	EncryptedDigest_constraint,
+	EncryptedDigest_decode_ber,
+	EncryptedDigest_encode_der,
+	EncryptedDigest_decode_xer,
+	EncryptedDigest_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_EncryptedDigest_tags_1,
+	sizeof(asn_DEF_EncryptedDigest_tags_1)
+		/sizeof(asn_DEF_EncryptedDigest_tags_1[0]), /* 1 */
+	asn_DEF_EncryptedDigest_tags_1,	/* Same as above */
+	sizeof(asn_DEF_EncryptedDigest_tags_1)
+		/sizeof(asn_DEF_EncryptedDigest_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/EncryptedDigest.h b/libkmod/pkcs7/asn1c-gen/EncryptedDigest.h
new file mode 100644
index 000000000000..7c202e4c5089
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/EncryptedDigest.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_EncryptedDigest_H_
+#define	_EncryptedDigest_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <OCTET_STRING.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* EncryptedDigest */
+typedef OCTET_STRING_t	 EncryptedDigest_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_EncryptedDigest;
+asn_struct_free_f EncryptedDigest_free;
+asn_struct_print_f EncryptedDigest_print;
+asn_constr_check_f EncryptedDigest_constraint;
+ber_type_decoder_f EncryptedDigest_decode_ber;
+der_type_encoder_f EncryptedDigest_encode_der;
+xer_type_decoder_f EncryptedDigest_decode_xer;
+xer_type_encoder_f EncryptedDigest_encode_xer;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _EncryptedDigest_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c b/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c
new file mode 100644
index 000000000000..e48187af0036
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c
@@ -0,0 +1,52 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "ExtendedCertificatesAndCertificates.h"
+
+static asn_TYPE_member_t asn_MBR_ExtendedCertificatesAndCertificates_1[] = {
+	{ ATF_OPEN_TYPE | ATF_POINTER, 0, 0,
+		-1 /* Ambiguous tag (ANY?) */,
+		0,
+		&asn_DEF_Certificate,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_ExtendedCertificatesAndCertificates_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_ExtendedCertificatesAndCertificates_specs_1 = {
+	sizeof(struct ExtendedCertificatesAndCertificates),
+	offsetof(struct ExtendedCertificatesAndCertificates, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_ExtendedCertificatesAndCertificates = {
+	"ExtendedCertificatesAndCertificates",
+	"ExtendedCertificatesAndCertificates",
+	SET_OF_free,
+	SET_OF_print,
+	SET_OF_constraint,
+	SET_OF_decode_ber,
+	SET_OF_encode_der,
+	SET_OF_decode_xer,
+	SET_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_ExtendedCertificatesAndCertificates_tags_1,
+	sizeof(asn_DEF_ExtendedCertificatesAndCertificates_tags_1)
+		/sizeof(asn_DEF_ExtendedCertificatesAndCertificates_tags_1[0]), /* 1 */
+	asn_DEF_ExtendedCertificatesAndCertificates_tags_1,	/* Same as above */
+	sizeof(asn_DEF_ExtendedCertificatesAndCertificates_tags_1)
+		/sizeof(asn_DEF_ExtendedCertificatesAndCertificates_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_ExtendedCertificatesAndCertificates_1,
+	1,	/* Single element */
+	&asn_SPC_ExtendedCertificatesAndCertificates_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h b/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h
new file mode 100644
index 000000000000..dfe92ccbeddc
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_ExtendedCertificatesAndCertificates_H_
+#define	_ExtendedCertificatesAndCertificates_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include "Certificate.h"
+#include <asn_SET_OF.h>
+#include <constr_SET_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ExtendedCertificatesAndCertificates */
+typedef struct ExtendedCertificatesAndCertificates {
+	A_SET_OF(Certificate_t) list;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} ExtendedCertificatesAndCertificates_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_ExtendedCertificatesAndCertificates;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _ExtendedCertificatesAndCertificates_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/INTEGER.c b/libkmod/pkcs7/asn1c-gen/INTEGER.c
new file mode 100644
index 000000000000..eed82176b509
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/INTEGER.c
@@ -0,0 +1,1025 @@
+/*-
+ * Copyright (c) 2003-2014 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <INTEGER.h>
+#include <asn_codecs_prim.h>	/* Encoder and decoder of a primitive type */
+#include <errno.h>
+
+/*
+ * INTEGER basic type description.
+ */
+static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_INTEGER = {
+	"INTEGER",
+	"INTEGER",
+	ASN__PRIMITIVE_TYPE_free,
+	INTEGER_print,
+	asn_generic_no_constraint,
+	ber_decode_primitive,
+	INTEGER_encode_der,
+	INTEGER_decode_xer,
+	INTEGER_encode_xer,
+#ifdef	ASN_DISABLE_PER_SUPPORT
+	0,
+	0,
+#else
+	INTEGER_decode_uper,	/* Unaligned PER decoder */
+	INTEGER_encode_uper,	/* Unaligned PER encoder */
+#endif	/* ASN_DISABLE_PER_SUPPORT */
+	0, /* Use generic outmost tag fetcher */
+	asn_DEF_INTEGER_tags,
+	sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
+	asn_DEF_INTEGER_tags,	/* Same as above */
+	sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
+/*
+ * Encode INTEGER type using DER.
+ */
+asn_enc_rval_t
+INTEGER_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
+	int tag_mode, ber_tlv_tag_t tag,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	INTEGER_t *st = (INTEGER_t *)sptr;
+
+	ASN_DEBUG("%s %s as INTEGER (tm=%d)",
+		cb?"Encoding":"Estimating", td->name, tag_mode);
+
+	/*
+	 * Canonicalize integer in the buffer.
+	 * (Remove too long sign extension, remove some first 0x00 bytes)
+	 */
+	if(st->buf) {
+		uint8_t *buf = st->buf;
+		uint8_t *end1 = buf + st->size - 1;
+		int shift;
+
+		/* Compute the number of superfluous leading bytes */
+		for(; buf < end1; buf++) {
+			/*
+			 * If the contents octets of an integer value encoding
+			 * consist of more than one octet, then the bits of the
+			 * first octet and bit 8 of the second octet:
+			 * a) shall not all be ones; and
+			 * b) shall not all be zero.
+			 */
+			switch(*buf) {
+			case 0x00: if((buf[1] & 0x80) == 0)
+					continue;
+				break;
+			case 0xff: if((buf[1] & 0x80))
+					continue;
+				break;
+			}
+			break;
+		}
+
+		/* Remove leading superfluous bytes from the integer */
+		shift = buf - st->buf;
+		if(shift) {
+			uint8_t *nb = st->buf;
+			uint8_t *end;
+
+			st->size -= shift;	/* New size, minus bad bytes */
+			end = nb + st->size;
+
+			for(; nb < end; nb++, buf++)
+				*nb = *buf;
+		}
+
+	} /* if(1) */
+
+	return der_encode_primitive(td, sptr, tag_mode, tag, cb, app_key);
+}
+
+static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop);
+
+/*
+ * INTEGER specific human-readable output.
+ */
+static ssize_t
+INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+	char scratch[32];	/* Enough for 64-bit integer */
+	uint8_t *buf = st->buf;
+	uint8_t *buf_end = st->buf + st->size;
+	signed long value;
+	ssize_t wrote = 0;
+	char *p;
+	int ret;
+
+	if(specs && specs->field_unsigned)
+		ret = asn_INTEGER2ulong(st, (unsigned long *)&value);
+	else
+		ret = asn_INTEGER2long(st, &value);
+
+	/* Simple case: the integer size is small */
+	if(ret == 0) {
+		const asn_INTEGER_enum_map_t *el;
+		size_t scrsize;
+		char *scr;
+
+		el = (value >= 0 || !specs || !specs->field_unsigned)
+			? INTEGER_map_value2enum(specs, value) : 0;
+		if(el) {
+			scrsize = el->enum_len + 32;
+			scr = (char *)alloca(scrsize);
+			if(plainOrXER == 0)
+				ret = snprintf(scr, scrsize,
+					"%ld (%s)", value, el->enum_name);
+			else
+				ret = snprintf(scr, scrsize,
+					"<%s/>", el->enum_name);
+		} else if(plainOrXER && specs && specs->strict_enumeration) {
+			ASN_DEBUG("ASN.1 forbids dealing with "
+				"unknown value of ENUMERATED type");
+			errno = EPERM;
+			return -1;
+		} else {
+			scrsize = sizeof(scratch);
+			scr = scratch;
+			ret = snprintf(scr, scrsize,
+				(specs && specs->field_unsigned)
+				?"%lu":"%ld", value);
+		}
+		assert(ret > 0 && (size_t)ret < scrsize);
+		return (cb(scr, ret, app_key) < 0) ? -1 : ret;
+	} else if(plainOrXER && specs && specs->strict_enumeration) {
+		/*
+		 * Here and earlier, we cannot encode the ENUMERATED values
+		 * if there is no corresponding identifier.
+		 */
+		ASN_DEBUG("ASN.1 forbids dealing with "
+			"unknown value of ENUMERATED type");
+		errno = EPERM;
+		return -1;
+	}
+
+	/* Output in the long xx:yy:zz... format */
+	/* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
+	for(p = scratch; buf < buf_end; buf++) {
+		const char * const h2c = "0123456789ABCDEF";
+		if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
+			/* Flush buffer */
+			if(cb(scratch, p - scratch, app_key) < 0)
+				return -1;
+			wrote += p - scratch;
+			p = scratch;
+		}
+		*p++ = h2c[*buf >> 4];
+		*p++ = h2c[*buf & 0x0F];
+		*p++ = 0x3a;	/* ":" */
+	}
+	if(p != scratch)
+		p--;	/* Remove the last ":" */
+
+	wrote += p - scratch;
+	return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;
+}
+
+/*
+ * INTEGER specific human-readable output.
+ */
+int
+INTEGER_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	const INTEGER_t *st = (const INTEGER_t *)sptr;
+	ssize_t ret;
+
+	(void)td;
+	(void)ilevel;
+
+	if(!st || !st->buf)
+		ret = cb("<absent>", 8, app_key);
+	else
+		ret = INTEGER__dump(td, st, cb, app_key, 0);
+
+	return (ret < 0) ? -1 : 0;
+}
+
+struct e2v_key {
+	const char *start;
+	const char *stop;
+	const asn_INTEGER_enum_map_t *vemap;
+	const unsigned int *evmap;
+};
+static int
+INTEGER__compar_enum2value(const void *kp, const void *am) {
+	const struct e2v_key *key = (const struct e2v_key *)kp;
+	const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
+	const char *ptr, *end, *name;
+
+	/* Remap the element (sort by different criterion) */
+	el = key->vemap + key->evmap[el - key->vemap];
+
+	/* Compare strings */
+	for(ptr = key->start, end = key->stop, name = el->enum_name;
+			ptr < end; ptr++, name++) {
+		if(*ptr != *name)
+			return *(const unsigned char *)ptr
+				- *(const unsigned char *)name;
+	}
+	return name[0] ? -1 : 0;
+}
+
+static const asn_INTEGER_enum_map_t *
+INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop) {
+	const asn_INTEGER_enum_map_t *el_found;
+	int count = specs ? specs->map_count : 0;
+	struct e2v_key key;
+	const char *lp;
+
+	if(!count) return NULL;
+
+	/* Guaranteed: assert(lstart < lstop); */
+	/* Figure out the tag name */
+	for(lstart++, lp = lstart; lp < lstop; lp++) {
+		switch(*lp) {
+		case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */
+		case 0x2f: /* '/' */ case 0x3e: /* '>' */
+			break;
+		default:
+			continue;
+		}
+		break;
+	}
+	if(lp == lstop) return NULL;	/* No tag found */
+	lstop = lp;
+
+	key.start = lstart;
+	key.stop = lstop;
+	key.vemap = specs->value2enum;
+	key.evmap = specs->enum2value;
+	el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,
+		specs->value2enum, count, sizeof(specs->value2enum[0]),
+		INTEGER__compar_enum2value);
+	if(el_found) {
+		/* Remap enum2value into value2enum */
+		el_found = key.vemap + key.evmap[el_found - key.vemap];
+	}
+	return el_found;
+}
+
+static int
+INTEGER__compar_value2enum(const void *kp, const void *am) {
+	long a = *(const long *)kp;
+	const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
+	long b = el->nat_value;
+	if(a < b) return -1;
+	else if(a == b) return 0;
+	else return 1;
+}
+
+const asn_INTEGER_enum_map_t *
+INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) {
+	int count = specs ? specs->map_count : 0;
+	if(!count) return 0;
+	return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,
+		count, sizeof(specs->value2enum[0]),
+		INTEGER__compar_value2enum);
+}
+
+static int
+INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
+	void *p = MALLOC(min_size + 1);
+	if(p) {
+		void *b = st->buf;
+		st->size = 0;
+		st->buf = p;
+		FREEMEM(b);
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+/*
+ * Decode the chunk of XML text encoding INTEGER.
+ */
+static enum xer_pbd_rval
+INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
+	INTEGER_t *st = (INTEGER_t *)sptr;
+	long dec_value;
+	long hex_value = 0;
+	const char *lp;
+	const char *lstart = (const char *)chunk_buf;
+	const char *lstop = lstart + chunk_size;
+	enum {
+		ST_LEADSPACE,
+		ST_SKIPSPHEX,
+		ST_WAITDIGITS,
+		ST_DIGITS,
+		ST_DIGITS_TRAILSPACE,
+		ST_HEXDIGIT1,
+		ST_HEXDIGIT2,
+		ST_HEXDIGITS_TRAILSPACE,
+		ST_HEXCOLON,
+		ST_END_ENUM,
+		ST_UNEXPECTED
+	} state = ST_LEADSPACE;
+	const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */
+	const char *dec_value_end = 0;
+
+	if(chunk_size)
+		ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
+			(long)chunk_size, *lstart, lstop[-1]);
+
+	if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
+		return XPBD_SYSTEM_FAILURE;
+
+	/*
+	 * We may have received a tag here. It will be processed inline.
+	 * Use strtoul()-like code and serialize the result.
+	 */
+	for(lp = lstart; lp < lstop; lp++) {
+		int lv = *lp;
+		switch(lv) {
+		case 0x09: case 0x0a: case 0x0d: case 0x20:
+			switch(state) {
+			case ST_LEADSPACE:
+			case ST_DIGITS_TRAILSPACE:
+			case ST_HEXDIGITS_TRAILSPACE:
+			case ST_SKIPSPHEX:
+				continue;
+			case ST_DIGITS:
+				dec_value_end = lp;
+				state = ST_DIGITS_TRAILSPACE;
+				continue;
+			case ST_HEXCOLON:
+				state = ST_HEXDIGITS_TRAILSPACE;
+				continue;
+			default:
+				break;
+			}
+			break;
+		case 0x2d:	/* '-' */
+			if(state == ST_LEADSPACE) {
+				dec_value = 0;
+				dec_value_start = lp;
+				state = ST_WAITDIGITS;
+				continue;
+			}
+			break;
+		case 0x2b:	/* '+' */
+			if(state == ST_LEADSPACE) {
+				dec_value = 0;
+				dec_value_start = lp;
+				state = ST_WAITDIGITS;
+				continue;
+			}
+			break;
+		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
+		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
+			switch(state) {
+			case ST_DIGITS: continue;
+			case ST_SKIPSPHEX:	/* Fall through */
+			case ST_HEXDIGIT1:
+				hex_value = (lv - 0x30) << 4;
+				state = ST_HEXDIGIT2;
+				continue;
+			case ST_HEXDIGIT2:
+				hex_value += (lv - 0x30);
+				state = ST_HEXCOLON;
+				st->buf[st->size++] = (uint8_t)hex_value;
+				continue;
+			case ST_HEXCOLON:
+				return XPBD_BROKEN_ENCODING;
+			case ST_LEADSPACE:
+				dec_value = 0;
+				dec_value_start = lp;
+				/* FALL THROUGH */
+			case ST_WAITDIGITS:
+				state = ST_DIGITS;
+				continue;
+			default:
+				break;
+			}
+			break;
+		case 0x3c:	/* '<', start of XML encoded enumeration */
+			if(state == ST_LEADSPACE) {
+				const asn_INTEGER_enum_map_t *el;
+				el = INTEGER_map_enum2value(
+					(asn_INTEGER_specifics_t *)
+					td->specifics, lstart, lstop);
+				if(el) {
+					ASN_DEBUG("Found \"%s\" => %ld",
+						el->enum_name, el->nat_value);
+					dec_value = el->nat_value;
+					state = ST_END_ENUM;
+					lp = lstop - 1;
+					continue;
+				}
+				ASN_DEBUG("Unknown identifier for INTEGER");
+			}
+			return XPBD_BROKEN_ENCODING;
+		case 0x3a:	/* ':' */
+			if(state == ST_HEXCOLON) {
+				/* This colon is expected */
+				state = ST_HEXDIGIT1;
+				continue;
+			} else if(state == ST_DIGITS) {
+				/* The colon here means that we have
+				 * decoded the first two hexadecimal
+				 * places as a decimal value.
+				 * Switch decoding mode. */
+				ASN_DEBUG("INTEGER re-evaluate as hex form");
+				state = ST_SKIPSPHEX;
+				dec_value_start = 0;
+				lp = lstart - 1;
+				continue;
+			} else {
+				ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart));
+				break;
+			}
+		/* [A-Fa-f] */
+		case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:
+		case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:
+			switch(state) {
+			case ST_SKIPSPHEX:
+			case ST_LEADSPACE: /* Fall through */
+			case ST_HEXDIGIT1:
+				hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61);
+				hex_value += 10;
+				hex_value <<= 4;
+				state = ST_HEXDIGIT2;
+				continue;
+			case ST_HEXDIGIT2:
+				hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61);
+				hex_value += 10;
+				st->buf[st->size++] = (uint8_t)hex_value;
+				state = ST_HEXCOLON;
+				continue;
+			case ST_DIGITS:
+				ASN_DEBUG("INTEGER re-evaluate as hex form");
+				state = ST_SKIPSPHEX;
+				dec_value_start = 0;
+				lp = lstart - 1;
+				continue;
+			default:
+				break;
+			}
+			break;
+		}
+
+		/* Found extra non-numeric stuff */
+		ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",
+			lv, (long)(lp - lstart));
+		state = ST_UNEXPECTED;
+		break;
+	}
+
+	switch(state) {
+	case ST_END_ENUM:
+		/* Got a complete and valid enumeration encoded as a tag. */
+		break;
+	case ST_DIGITS:
+		dec_value_end = lstop;
+		/* FALL THROUGH */
+	case ST_DIGITS_TRAILSPACE:
+		/* The last symbol encountered was a digit. */
+		switch(asn_strtol_lim(dec_value_start, &dec_value_end, &dec_value)) {
+		case ASN_STRTOL_OK:
+			break;
+		case ASN_STRTOL_ERROR_RANGE:
+			return XPBD_DECODER_LIMIT;
+		case ASN_STRTOL_ERROR_INVAL:
+		case ASN_STRTOL_EXPECT_MORE:
+		case ASN_STRTOL_EXTRA_DATA:
+			return XPBD_BROKEN_ENCODING;
+		}
+		break;
+	case ST_HEXCOLON:
+	case ST_HEXDIGITS_TRAILSPACE:
+		st->buf[st->size] = 0;	/* Just in case termination */
+		return XPBD_BODY_CONSUMED;
+	case ST_HEXDIGIT1:
+	case ST_HEXDIGIT2:
+	case ST_SKIPSPHEX:
+		return XPBD_BROKEN_ENCODING;
+	case ST_LEADSPACE:
+		/* Content not found */
+		return XPBD_NOT_BODY_IGNORE;
+	case ST_WAITDIGITS:
+	case ST_UNEXPECTED:
+		ASN_DEBUG("INTEGER: No useful digits (state %d)", state);
+		return XPBD_BROKEN_ENCODING;	/* No digits */
+	}
+
+	/*
+	 * Convert the result of parsing of enumeration or a straight
+	 * decimal value into a BER representation.
+	 */
+	if(asn_long2INTEGER(st, dec_value))
+		return XPBD_SYSTEM_FAILURE;
+
+	return XPBD_BODY_CONSUMED;
+}
+
+asn_dec_rval_t
+INTEGER_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
+		const void *buf_ptr, size_t size) {
+
+	return xer_decode_primitive(opt_codec_ctx, td,
+		sptr, sizeof(INTEGER_t), opt_mname,
+		buf_ptr, size, INTEGER__xer_body_decode);
+}
+
+asn_enc_rval_t
+INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	const INTEGER_t *st = (const INTEGER_t *)sptr;
+	asn_enc_rval_t er;
+
+	(void)ilevel;
+	(void)flags;
+	
+	if(!st || !st->buf)
+		ASN__ENCODE_FAILED;
+
+	er.encoded = INTEGER__dump(td, st, cb, app_key, 1);
+	if(er.encoded < 0) ASN__ENCODE_FAILED;
+
+	ASN__ENCODED_OK(er);
+}
+
+#ifndef	ASN_DISABLE_PER_SUPPORT
+
+asn_dec_rval_t
+INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+	asn_dec_rval_t rval = { RC_OK, 0 };
+	INTEGER_t *st = (INTEGER_t *)*sptr;
+	asn_per_constraint_t *ct;
+	int repeat;
+
+	(void)opt_codec_ctx;
+
+	if(!st) {
+		st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
+		if(!st) ASN__DECODE_FAILED;
+	}
+
+	if(!constraints) constraints = td->per_constraints;
+	ct = constraints ? &constraints->value : 0;
+
+	if(ct && ct->flags & APC_EXTENSIBLE) {
+		int inext = per_get_few_bits(pd, 1);
+		if(inext < 0) ASN__DECODE_STARVED;
+		if(inext) ct = 0;
+	}
+
+	FREEMEM(st->buf);
+	st->buf = 0;
+	st->size = 0;
+	if(ct) {
+		if(ct->flags & APC_SEMI_CONSTRAINED) {
+			st->buf = (uint8_t *)CALLOC(1, 2);
+			if(!st->buf) ASN__DECODE_FAILED;
+			st->size = 1;
+		} else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
+			size_t size = (ct->range_bits + 7) >> 3;
+			st->buf = (uint8_t *)MALLOC(1 + size + 1);
+			if(!st->buf) ASN__DECODE_FAILED;
+			st->size = size;
+		}
+	}
+
+	/* X.691-2008/11, #13.2.2, constrained whole number */
+	if(ct && ct->flags != APC_UNCONSTRAINED) {
+		/* #11.5.6 */
+		ASN_DEBUG("Integer with range %d bits", ct->range_bits);
+		if(ct->range_bits >= 0) {
+			if((size_t)ct->range_bits > 8 * sizeof(unsigned long))
+				ASN__DECODE_FAILED;
+
+			if(specs && specs->field_unsigned) {
+				unsigned long uvalue;
+				if(uper_get_constrained_whole_number(pd,
+					&uvalue, ct->range_bits))
+					ASN__DECODE_STARVED;
+				ASN_DEBUG("Got value %lu + low %ld",
+					uvalue, ct->lower_bound);
+				uvalue += ct->lower_bound;
+				if(asn_ulong2INTEGER(st, uvalue))
+					ASN__DECODE_FAILED;
+			} else {
+				unsigned long svalue;
+				if(uper_get_constrained_whole_number(pd,
+					&svalue, ct->range_bits))
+					ASN__DECODE_STARVED;
+				ASN_DEBUG("Got value %ld + low %ld",
+					svalue, ct->lower_bound);
+				svalue += ct->lower_bound;
+				if(asn_long2INTEGER(st, svalue))
+					ASN__DECODE_FAILED;
+			}
+			return rval;
+		}
+	} else {
+		ASN_DEBUG("Decoding unconstrained integer %s", td->name);
+	}
+
+	/* X.691, #12.2.3, #12.2.4 */
+	do {
+		ssize_t len;
+		void *p;
+		int ret;
+
+		/* Get the PER length */
+		len = uper_get_length(pd, -1, &repeat);
+		if(len < 0) ASN__DECODE_STARVED;
+
+		p = REALLOC(st->buf, st->size + len + 1);
+		if(!p) ASN__DECODE_FAILED;
+		st->buf = (uint8_t *)p;
+
+		ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
+		if(ret < 0) ASN__DECODE_STARVED;
+		st->size += len;
+	} while(repeat);
+	st->buf[st->size] = 0;	/* JIC */
+
+	/* #12.2.3 */
+	if(ct && ct->lower_bound) {
+		/*
+		 * TODO: replace by in-place arithmetics.
+		 */
+		long value;
+		if(asn_INTEGER2long(st, &value))
+			ASN__DECODE_FAILED;
+		if(asn_long2INTEGER(st, value + ct->lower_bound))
+			ASN__DECODE_FAILED;
+	}
+
+	return rval;
+}
+
+asn_enc_rval_t
+INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+	asn_enc_rval_t er;
+	INTEGER_t *st = (INTEGER_t *)sptr;
+	const uint8_t *buf;
+	const uint8_t *end;
+	asn_per_constraint_t *ct;
+	long value = 0;
+	unsigned long v = 0;
+
+	if(!st || st->size == 0) ASN__ENCODE_FAILED;
+
+	if(!constraints) constraints = td->per_constraints;
+	ct = constraints ? &constraints->value : 0;
+
+	er.encoded = 0;
+
+	if(ct) {
+		int inext = 0;
+		if(specs && specs->field_unsigned) {
+			unsigned long uval;
+			if(asn_INTEGER2ulong(st, &uval))
+				ASN__ENCODE_FAILED;
+			/* Check proper range */
+			if(ct->flags & APC_SEMI_CONSTRAINED) {
+				if(uval < (unsigned long)ct->lower_bound)
+					inext = 1;
+			} else if(ct->range_bits >= 0) {
+				if(uval < (unsigned long)ct->lower_bound
+				|| uval > (unsigned long)ct->upper_bound)
+					inext = 1;
+			}
+			ASN_DEBUG("Value %lu (%02x/%d) lb %lu ub %lu %s",
+				uval, st->buf[0], st->size,
+				ct->lower_bound, ct->upper_bound,
+				inext ? "ext" : "fix");
+			value = uval;
+		} else {
+			if(asn_INTEGER2long(st, &value))
+				ASN__ENCODE_FAILED;
+			/* Check proper range */
+			if(ct->flags & APC_SEMI_CONSTRAINED) {
+				if(value < ct->lower_bound)
+					inext = 1;
+			} else if(ct->range_bits >= 0) {
+				if(value < ct->lower_bound
+				|| value > ct->upper_bound)
+					inext = 1;
+			}
+			ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
+				value, st->buf[0], st->size,
+				ct->lower_bound, ct->upper_bound,
+				inext ? "ext" : "fix");
+		}
+		if(ct->flags & APC_EXTENSIBLE) {
+			if(per_put_few_bits(po, inext, 1))
+				ASN__ENCODE_FAILED;
+			if(inext) ct = 0;
+		} else if(inext) {
+			ASN__ENCODE_FAILED;
+		}
+	}
+
+
+	/* X.691-11/2008, #13.2.2, test if constrained whole number */
+	if(ct && ct->range_bits >= 0) {
+		/* #11.5.6 -> #11.3 */
+		ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",
+			value, value - ct->lower_bound, ct->range_bits);
+		v = value - ct->lower_bound;
+		if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))
+			ASN__ENCODE_FAILED;
+		ASN__ENCODED_OK(er);
+	}
+
+	if(ct && ct->lower_bound) {
+		ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
+		/* TODO: adjust lower bound */
+		ASN__ENCODE_FAILED;
+	}
+
+	for(buf = st->buf, end = st->buf + st->size; buf < end;) {
+		ssize_t mayEncode = uper_put_length(po, end - buf);
+		if(mayEncode < 0)
+			ASN__ENCODE_FAILED;
+		if(per_put_many_bits(po, buf, 8 * mayEncode))
+			ASN__ENCODE_FAILED;
+		buf += mayEncode;
+	}
+
+	ASN__ENCODED_OK(er);
+}
+
+#endif	/* ASN_DISABLE_PER_SUPPORT */
+
+int
+asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
+	uint8_t *b, *end;
+	size_t size;
+	long l;
+
+	/* Sanity checking */
+	if(!iptr || !iptr->buf || !lptr) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Cache the begin/end of the buffer */
+	b = iptr->buf;	/* Start of the INTEGER buffer */
+	size = iptr->size;
+	end = b + size;	/* Where to stop */
+
+	if(size > sizeof(long)) {
+		uint8_t *end1 = end - 1;
+		/*
+		 * Slightly more advanced processing,
+		 * able to >sizeof(long) bytes,
+		 * when the actual value is small
+		 * (0x0000000000abcdef would yield a fine 0x00abcdef)
+		 */
+		/* Skip out the insignificant leading bytes */
+		for(; b < end1; b++) {
+			switch(*b) {
+			case 0x00: if((b[1] & 0x80) == 0) continue; break;
+			case 0xff: if((b[1] & 0x80) != 0) continue; break;
+			}
+			break;
+		}
+
+		size = end - b;
+		if(size > sizeof(long)) {
+			/* Still cannot fit the long */
+			errno = ERANGE;
+			return -1;
+		}
+	}
+
+	/* Shortcut processing of a corner case */
+	if(end == b) {
+		*lptr = 0;
+		return 0;
+	}
+
+	/* Perform the sign initialization */
+	/* Actually l = -(*b >> 7); gains nothing, yet unreadable! */
+	if((*b >> 7)) l = -1; else l = 0;
+
+	/* Conversion engine */
+	for(; b < end; b++)
+		l = (l << 8) | *b;
+
+	*lptr = l;
+	return 0;
+}
+
+int
+asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
+	uint8_t *b, *end;
+	unsigned long l;
+	size_t size;
+
+	if(!iptr || !iptr->buf || !lptr) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	b = iptr->buf;
+	size = iptr->size;
+	end = b + size;
+
+	/* If all extra leading bytes are zeroes, ignore them */
+	for(; size > sizeof(unsigned long); b++, size--) {
+		if(*b) {
+			/* Value won't fit unsigned long */
+			errno = ERANGE;
+			return -1;
+		}
+	}
+
+	/* Conversion engine */
+	for(l = 0; b < end; b++)
+		l = (l << 8) | *b;
+
+	*lptr = l;
+	return 0;
+}
+
+int
+asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
+	uint8_t *buf;
+	uint8_t *end;
+	uint8_t *b;
+	int shr;
+
+	if(value <= LONG_MAX)
+		return asn_long2INTEGER(st, value);
+
+	buf = (uint8_t *)MALLOC(1 + sizeof(value));
+	if(!buf) return -1;
+
+	end = buf + (sizeof(value) + 1);
+	buf[0] = 0;
+	for(b = buf + 1, shr = (sizeof(long)-1)*8; b < end; shr -= 8, b++)
+		*b = (uint8_t)(value >> shr);
+
+	if(st->buf) FREEMEM(st->buf);
+	st->buf = buf;
+	st->size = 1 + sizeof(value);
+
+	return 0;
+}
+
+int
+asn_long2INTEGER(INTEGER_t *st, long value) {
+	uint8_t *buf, *bp;
+	uint8_t *p;
+	uint8_t *pstart;
+	uint8_t *pend1;
+	int littleEndian = 1;	/* Run-time detection */
+	int add;
+
+	if(!st) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	buf = (uint8_t *)MALLOC(sizeof(value));
+	if(!buf) return -1;
+
+	if(*(char *)&littleEndian) {
+		pstart = (uint8_t *)&value + sizeof(value) - 1;
+		pend1 = (uint8_t *)&value;
+		add = -1;
+	} else {
+		pstart = (uint8_t *)&value;
+		pend1 = pstart + sizeof(value) - 1;
+		add = 1;
+	}
+
+	/*
+	 * If the contents octet consists of more than one octet,
+	 * then bits of the first octet and bit 8 of the second octet:
+	 * a) shall not all be ones; and
+	 * b) shall not all be zero.
+	 */
+	for(p = pstart; p != pend1; p += add) {
+		switch(*p) {
+		case 0x00: if((*(p+add) & 0x80) == 0)
+				continue;
+			break;
+		case 0xff: if((*(p+add) & 0x80))
+				continue;
+			break;
+		}
+		break;
+	}
+	/* Copy the integer body */
+	for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
+		*bp++ = *p;
+
+	if(st->buf) FREEMEM(st->buf);
+	st->buf = buf;
+	st->size = bp - buf;
+
+	return 0;
+}
+
+/*
+ * This function is going to be DEPRECATED soon.
+ */
+enum asn_strtol_result_e
+asn_strtol(const char *str, const char *end, long *lp) {
+    const char *endp = end;
+
+    switch(asn_strtol_lim(str, &endp, lp)) {
+    case ASN_STRTOL_ERROR_RANGE:
+        return ASN_STRTOL_ERROR_RANGE;
+    case ASN_STRTOL_ERROR_INVAL:
+        return ASN_STRTOL_ERROR_INVAL;
+    case ASN_STRTOL_EXPECT_MORE:
+        return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
+    case ASN_STRTOL_OK:
+        return ASN_STRTOL_OK;
+    case ASN_STRTOL_EXTRA_DATA:
+        return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
+    }
+
+    return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
+}
+
+/*
+ * Parse the number in the given string until the given *end position,
+ * returning the position after the last parsed character back using the
+ * same (*end) pointer.
+ * WARNING: This behavior is different from the standard strtol(3).
+ */
+enum asn_strtol_result_e
+asn_strtol_lim(const char *str, const char **end, long *lp) {
+	int sign = 1;
+	long l;
+
+	const long upper_boundary = LONG_MAX / 10;
+	long last_digit_max = LONG_MAX % 10;
+
+	if(str >= *end) return ASN_STRTOL_ERROR_INVAL;
+
+	switch(*str) {
+	case '-':
+		last_digit_max++;
+		sign = -1;
+		/* FALL THROUGH */
+	case '+':
+		str++;
+		if(str >= *end) {
+			*end = str;
+			return ASN_STRTOL_EXPECT_MORE;
+		}
+	}
+
+	for(l = 0; str < (*end); str++) {
+		switch(*str) {
+		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
+		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {
+			int d = *str - '0';
+			if(l < upper_boundary) {
+				l = l * 10 + d;
+			} else if(l == upper_boundary) {
+				if(d <= last_digit_max) {
+					if(sign > 0) {
+						l = l * 10 + d;
+					} else {
+						sign = 1;
+						l = -l * 10 - d;
+					}
+				} else {
+					*end = str;
+					return ASN_STRTOL_ERROR_RANGE;
+				}
+			} else {
+				*end = str;
+				return ASN_STRTOL_ERROR_RANGE;
+			}
+		    }
+		    continue;
+		default:
+		    *end = str;
+		    *lp = sign * l;
+		    return ASN_STRTOL_EXTRA_DATA;
+		}
+	}
+
+	*end = str;
+	*lp = sign * l;
+	return ASN_STRTOL_OK;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/INTEGER.h b/libkmod/pkcs7/asn1c-gen/INTEGER.h
new file mode 100644
index 000000000000..9a8809707577
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/INTEGER.h
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_INTEGER_H_
+#define	_INTEGER_H_
+
+#include <asn_application.h>
+#include <asn_codecs_prim.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
+
+extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
+
+/* Map with <tag> to integer value association */
+typedef struct asn_INTEGER_enum_map_s {
+	long		 nat_value;	/* associated native integer value */
+	size_t		 enum_len;	/* strlen("tag") */
+	const char	*enum_name;	/* "tag" */
+} asn_INTEGER_enum_map_t;
+
+/* This type describes an enumeration for INTEGER and ENUMERATED types */
+typedef const struct asn_INTEGER_specifics_s {
+	const asn_INTEGER_enum_map_t *value2enum;	/* N -> "tag"; sorted by N */
+	const unsigned int *enum2value;		/* "tag" => N; sorted by tag */
+	int map_count;				/* Elements in either map */
+	int extension;				/* This map is extensible */
+	int strict_enumeration;			/* Enumeration set is fixed */
+	int field_width;			/* Size of native integer */
+	int field_unsigned;			/* Signed=0, unsigned=1 */
+} asn_INTEGER_specifics_t;
+
+asn_struct_print_f INTEGER_print;
+ber_type_decoder_f INTEGER_decode_ber;
+der_type_encoder_f INTEGER_encode_der;
+xer_type_decoder_f INTEGER_decode_xer;
+xer_type_encoder_f INTEGER_encode_xer;
+per_type_decoder_f INTEGER_decode_uper;
+per_type_encoder_f INTEGER_encode_uper;
+
+/***********************************
+ * Some handy conversion routines. *
+ ***********************************/
+
+/*
+ * Returns 0 if it was possible to convert, -1 otherwise.
+ * -1/EINVAL: Mandatory argument missing
+ * -1/ERANGE: Value encoded is out of range for long representation
+ * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
+ */
+int asn_INTEGER2long(const INTEGER_t *i, long *l);
+int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l);
+int asn_long2INTEGER(INTEGER_t *i, long l);
+int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l);
+
+/* A a reified version of strtol(3) with nicer error reporting. */
+enum asn_strtol_result_e {
+    ASN_STRTOL_ERROR_RANGE = -3,  /* Input outside of numeric range for long type */
+    ASN_STRTOL_ERROR_INVAL = -2,  /* Invalid data encountered (e.g., "+-") */
+    ASN_STRTOL_EXPECT_MORE = -1,  /* More data expected (e.g. "+") */
+    ASN_STRTOL_OK          =  0,  /* Conversion succeded, number ends at (*end) */
+    ASN_STRTOL_EXTRA_DATA  =  1   /* Conversion succeded, but the string has extra stuff */
+};
+enum asn_strtol_result_e asn_strtol_lim(const char *str, const char **end, long *l);
+
+/* The asn_strtol is going to be DEPRECATED soon */
+enum asn_strtol_result_e asn_strtol(const char *str, const char *end, long *l);
+
+/*
+ * Convert the integer value into the corresponding enumeration map entry.
+ */
+const asn_INTEGER_enum_map_t *INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _INTEGER_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c b/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c
new file mode 100644
index 000000000000..885de3cbc498
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c
@@ -0,0 +1,65 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "IssuerAndSerialNumber.h"
+
+static asn_TYPE_member_t asn_MBR_IssuerAndSerialNumber_1[] = {
+	{ ATF_OPEN_TYPE | ATF_NOFLAGS, 0, offsetof(struct IssuerAndSerialNumber, issuer),
+		-1 /* Ambiguous tag (ANY?) */,
+		0,
+		&asn_DEF_ANY,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"issuer"
+		},
+	{ ATF_OPEN_TYPE | ATF_NOFLAGS, 0, offsetof(struct IssuerAndSerialNumber, serialNumber),
+		-1 /* Ambiguous tag (ANY?) */,
+		0,
+		&asn_DEF_ANY,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"serialNumber"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_IssuerAndSerialNumber_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SEQUENCE_specifics_t asn_SPC_IssuerAndSerialNumber_specs_1 = {
+	sizeof(struct IssuerAndSerialNumber),
+	offsetof(struct IssuerAndSerialNumber, _asn_ctx),
+	0,	/* No top level tags */
+	0,	/* No tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_IssuerAndSerialNumber = {
+	"IssuerAndSerialNumber",
+	"IssuerAndSerialNumber",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_IssuerAndSerialNumber_tags_1,
+	sizeof(asn_DEF_IssuerAndSerialNumber_tags_1)
+		/sizeof(asn_DEF_IssuerAndSerialNumber_tags_1[0]), /* 1 */
+	asn_DEF_IssuerAndSerialNumber_tags_1,	/* Same as above */
+	sizeof(asn_DEF_IssuerAndSerialNumber_tags_1)
+		/sizeof(asn_DEF_IssuerAndSerialNumber_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_IssuerAndSerialNumber_1,
+	2,	/* Elements count */
+	&asn_SPC_IssuerAndSerialNumber_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h b/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h
new file mode 100644
index 000000000000..477fd0ccbcef
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_IssuerAndSerialNumber_H_
+#define	_IssuerAndSerialNumber_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <ANY.h>
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* IssuerAndSerialNumber */
+typedef struct IssuerAndSerialNumber {
+	ANY_t	 issuer;
+	ANY_t	 serialNumber;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} IssuerAndSerialNumber_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_IssuerAndSerialNumber;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _IssuerAndSerialNumber_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/Makefile.am.sample b/libkmod/pkcs7/asn1c-gen/Makefile.am.sample
new file mode 100644
index 000000000000..122279af6bbd
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Makefile.am.sample
@@ -0,0 +1,150 @@
+ASN_MODULE_SOURCES=	\
+	PKCS7ContentInfo.c	\
+	ContentType.c	\
+	SignedData.c	\
+	ContentInfo.c	\
+	Data.c	\
+	DigestAlgorithmIdentifiers.c	\
+	DigestAlgorithmIdentifier.c	\
+	ExtendedCertificatesAndCertificates.c	\
+	Certificates.c	\
+	CertificateRevocationLists.c	\
+	CertificateList.c	\
+	CRLSequence.c	\
+	Certificate.c	\
+	SignerInfos.c	\
+	SignerInfo.c	\
+	SignerIdentifier.c	\
+	IssuerAndSerialNumber.c	\
+	CertificateSerialNumber.c	\
+	SubjectKeyIdentifier.c	\
+	SetOfAuthenticatedAttribute.c	\
+	Values.c	\
+	AuthenticatedAttribute.c	\
+	UnauthenticatedAttribute.c	\
+	DigestEncryptionAlgorithmIdentifier.c	\
+	EncryptedDigest.c	\
+	Name.c	\
+	RelativeDistinguishedName.c	\
+	AttributeValueAssertion.c
+
+ASN_MODULE_HEADERS=	\
+	PKCS7ContentInfo.h	\
+	ContentType.h	\
+	SignedData.h	\
+	ContentInfo.h	\
+	Data.h	\
+	DigestAlgorithmIdentifiers.h	\
+	DigestAlgorithmIdentifier.h	\
+	ExtendedCertificatesAndCertificates.h	\
+	Certificates.h	\
+	CertificateRevocationLists.h	\
+	CertificateList.h	\
+	CRLSequence.h	\
+	Certificate.h	\
+	SignerInfos.h	\
+	SignerInfo.h	\
+	SignerIdentifier.h	\
+	IssuerAndSerialNumber.h	\
+	CertificateSerialNumber.h	\
+	SubjectKeyIdentifier.h	\
+	SetOfAuthenticatedAttribute.h	\
+	Values.h	\
+	AuthenticatedAttribute.h	\
+	UnauthenticatedAttribute.h	\
+	DigestEncryptionAlgorithmIdentifier.h	\
+	EncryptedDigest.h	\
+	Name.h	\
+	RelativeDistinguishedName.h	\
+	AttributeValueAssertion.h
+
+ASN_MODULE_HEADERS+=ANY.h
+ASN_MODULE_SOURCES+=ANY.c
+ASN_MODULE_HEADERS+=INTEGER.h
+ASN_MODULE_HEADERS+=NativeEnumerated.h
+ASN_MODULE_SOURCES+=INTEGER.c
+ASN_MODULE_SOURCES+=NativeEnumerated.c
+ASN_MODULE_HEADERS+=NativeInteger.h
+ASN_MODULE_SOURCES+=NativeInteger.c
+ASN_MODULE_HEADERS+=OBJECT_IDENTIFIER.h
+ASN_MODULE_SOURCES+=OBJECT_IDENTIFIER.c
+ASN_MODULE_HEADERS+=asn_SEQUENCE_OF.h
+ASN_MODULE_SOURCES+=asn_SEQUENCE_OF.c
+ASN_MODULE_HEADERS+=asn_SET_OF.h
+ASN_MODULE_SOURCES+=asn_SET_OF.c
+ASN_MODULE_HEADERS+=constr_CHOICE.h
+ASN_MODULE_SOURCES+=constr_CHOICE.c
+ASN_MODULE_HEADERS+=constr_SEQUENCE.h
+ASN_MODULE_SOURCES+=constr_SEQUENCE.c
+ASN_MODULE_HEADERS+=constr_SEQUENCE_OF.h
+ASN_MODULE_SOURCES+=constr_SEQUENCE_OF.c
+ASN_MODULE_HEADERS+=constr_SET_OF.h
+ASN_MODULE_SOURCES+=constr_SET_OF.c
+ASN_MODULE_HEADERS+=asn_application.h
+ASN_MODULE_HEADERS+=asn_system.h
+ASN_MODULE_HEADERS+=asn_codecs.h
+ASN_MODULE_HEADERS+=asn_internal.h
+ASN_MODULE_HEADERS+=OCTET_STRING.h
+ASN_MODULE_SOURCES+=OCTET_STRING.c
+ASN_MODULE_HEADERS+=BIT_STRING.h
+ASN_MODULE_SOURCES+=BIT_STRING.c
+ASN_MODULE_SOURCES+=asn_codecs_prim.c
+ASN_MODULE_HEADERS+=asn_codecs_prim.h
+ASN_MODULE_HEADERS+=ber_tlv_length.h
+ASN_MODULE_SOURCES+=ber_tlv_length.c
+ASN_MODULE_HEADERS+=ber_tlv_tag.h
+ASN_MODULE_SOURCES+=ber_tlv_tag.c
+ASN_MODULE_HEADERS+=ber_decoder.h
+ASN_MODULE_SOURCES+=ber_decoder.c
+ASN_MODULE_HEADERS+=der_encoder.h
+ASN_MODULE_SOURCES+=der_encoder.c
+ASN_MODULE_HEADERS+=constr_TYPE.h
+ASN_MODULE_SOURCES+=constr_TYPE.c
+ASN_MODULE_HEADERS+=constraints.h
+ASN_MODULE_SOURCES+=constraints.c
+ASN_MODULE_HEADERS+=xer_support.h
+ASN_MODULE_SOURCES+=xer_support.c
+ASN_MODULE_HEADERS+=xer_decoder.h
+ASN_MODULE_SOURCES+=xer_decoder.c
+ASN_MODULE_HEADERS+=xer_encoder.h
+ASN_MODULE_SOURCES+=xer_encoder.c
+ASN_MODULE_HEADERS+=per_support.h
+ASN_MODULE_SOURCES+=per_support.c
+ASN_MODULE_HEADERS+=per_decoder.h
+ASN_MODULE_SOURCES+=per_decoder.c
+ASN_MODULE_HEADERS+=per_encoder.h
+ASN_MODULE_SOURCES+=per_encoder.c
+ASN_MODULE_HEADERS+=per_opentype.h
+ASN_MODULE_SOURCES+=per_opentype.c
+ASN_CONVERTER_SOURCES+=converter-sample.c
+
+
+lib_LTLIBRARIES=libsomething.la
+libsomething_la_SOURCES=$(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
+
+# This file may be used as an input for make(3)
+# Remove the lines below to convert it into a pure .am file
+TARGET = progname
+CFLAGS += -I.
+OBJS=${ASN_MODULE_SOURCES:.c=.o} ${ASN_CONVERTER_SOURCES:.c=.o}
+
+all: $(TARGET)
+
+$(TARGET): ${OBJS}
+	$(CC) $(CFLAGS) -o $(TARGET) ${OBJS} $(LDFLAGS) $(LIBS)
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+
+.c.o:
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+clean:
+	rm -f $(TARGET)
+	rm -f $(OBJS)
+
+regen: regenerate-from-asn1-source
+
+regenerate-from-asn1-source:
+	asn1c -fwide-types ../pkcs7.asn1
+
diff --git a/libkmod/pkcs7/asn1c-gen/Name.c b/libkmod/pkcs7/asn1c-gen/Name.c
new file mode 100644
index 000000000000..917727f2a807
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Name.c
@@ -0,0 +1,52 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "Name.h"
+
+static asn_TYPE_member_t asn_MBR_Name_1[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
+		0,
+		&asn_DEF_RelativeDistinguishedName,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_Name_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_Name_specs_1 = {
+	sizeof(struct Name),
+	offsetof(struct Name, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_Name = {
+	"Name",
+	"Name",
+	SEQUENCE_OF_free,
+	SEQUENCE_OF_print,
+	SEQUENCE_OF_constraint,
+	SEQUENCE_OF_decode_ber,
+	SEQUENCE_OF_encode_der,
+	SEQUENCE_OF_decode_xer,
+	SEQUENCE_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_Name_tags_1,
+	sizeof(asn_DEF_Name_tags_1)
+		/sizeof(asn_DEF_Name_tags_1[0]), /* 1 */
+	asn_DEF_Name_tags_1,	/* Same as above */
+	sizeof(asn_DEF_Name_tags_1)
+		/sizeof(asn_DEF_Name_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_Name_1,
+	1,	/* Single element */
+	&asn_SPC_Name_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/Name.h b/libkmod/pkcs7/asn1c-gen/Name.h
new file mode 100644
index 000000000000..fcb146344087
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Name.h
@@ -0,0 +1,44 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_Name_H_
+#define	_Name_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <asn_SEQUENCE_OF.h>
+#include <constr_SEQUENCE_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct RelativeDistinguishedName;
+
+/* Name */
+typedef struct Name {
+	A_SEQUENCE_OF(struct RelativeDistinguishedName) list;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} Name_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_Name;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "RelativeDistinguishedName.h"
+
+#endif	/* _Name_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/NativeEnumerated.c b/libkmod/pkcs7/asn1c-gen/NativeEnumerated.c
new file mode 100644
index 000000000000..78366af31840
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/NativeEnumerated.c
@@ -0,0 +1,207 @@
+/*-
+ * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+/*
+ * Read the NativeInteger.h for the explanation wrt. differences between
+ * INTEGER and NativeInteger.
+ * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
+ * implementation deals with the standard (machine-specific) representation
+ * of them instead of using the platform-independent buffer.
+ */
+#include <asn_internal.h>
+#include <NativeEnumerated.h>
+
+/*
+ * NativeEnumerated basic type description.
+ */
+static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
+	"ENUMERATED",			/* The ASN.1 type is still ENUMERATED */
+	"ENUMERATED",
+	NativeInteger_free,
+	NativeInteger_print,
+	asn_generic_no_constraint,
+	NativeInteger_decode_ber,
+	NativeInteger_encode_der,
+	NativeInteger_decode_xer,
+	NativeEnumerated_encode_xer,
+	NativeEnumerated_decode_uper,
+	NativeEnumerated_encode_uper,
+	0, /* Use generic outmost tag fetcher */
+	asn_DEF_NativeEnumerated_tags,
+	sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
+	asn_DEF_NativeEnumerated_tags,	/* Same as above */
+	sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
+asn_enc_rval_t
+NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+        int ilevel, enum xer_encoder_flags_e flags,
+                asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+        asn_enc_rval_t er;
+        const long *native = (const long *)sptr;
+	const asn_INTEGER_enum_map_t *el;
+
+        (void)ilevel;
+        (void)flags;
+
+        if(!native) ASN__ENCODE_FAILED;
+
+	el = INTEGER_map_value2enum(specs, *native);
+	if(el) {
+		size_t srcsize = el->enum_len + 5;
+		char *src = (char *)alloca(srcsize);
+
+		er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name);
+		assert(er.encoded > 0 && (size_t)er.encoded < srcsize);
+		if(cb(src, er.encoded, app_key) < 0) ASN__ENCODE_FAILED;
+		ASN__ENCODED_OK(er);
+	} else {
+		ASN_DEBUG("ASN.1 forbids dealing with "
+			"unknown value of ENUMERATED type");
+		ASN__ENCODE_FAILED;
+	}
+}
+
+asn_dec_rval_t
+NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+	void **sptr, asn_per_data_t *pd) {
+	asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
+	asn_dec_rval_t rval = { RC_OK, 0 };
+	long *native = (long *)*sptr;
+	asn_per_constraint_t *ct;
+	long value;
+
+	(void)opt_codec_ctx;
+
+	if(constraints) ct = &constraints->value;
+	else if(td->per_constraints) ct = &td->per_constraints->value;
+	else ASN__DECODE_FAILED;	/* Mandatory! */
+	if(!specs) ASN__DECODE_FAILED;
+
+	if(!native) {
+		native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
+		if(!native) ASN__DECODE_FAILED;
+	}
+
+	ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
+
+	if(ct->flags & APC_EXTENSIBLE) {
+		int inext = per_get_few_bits(pd, 1);
+		if(inext < 0) ASN__DECODE_STARVED;
+		if(inext) ct = 0;
+	}
+
+	if(ct && ct->range_bits >= 0) {
+		value = per_get_few_bits(pd, ct->range_bits);
+		if(value < 0) ASN__DECODE_STARVED;
+		if(value >= (specs->extension
+			? specs->extension - 1 : specs->map_count))
+			ASN__DECODE_FAILED;
+	} else {
+		if(!specs->extension)
+			ASN__DECODE_FAILED;
+		/*
+		 * X.691, #10.6: normally small non-negative whole number;
+		 */
+		value = uper_get_nsnnwn(pd);
+		if(value < 0) ASN__DECODE_STARVED;
+		value += specs->extension - 1;
+		if(value >= specs->map_count)
+			ASN__DECODE_FAILED;
+	}
+
+	*native = specs->value2enum[value].nat_value;
+	ASN_DEBUG("Decoded %s = %ld", td->name, *native);
+
+	return rval;
+}
+
+static int
+NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
+	const asn_INTEGER_enum_map_t *a = ap;
+	const asn_INTEGER_enum_map_t *b = bp;
+	if(a->nat_value == b->nat_value)
+		return 0;
+	if(a->nat_value < b->nat_value)
+		return -1;
+	return 1;
+}
+
+asn_enc_rval_t
+NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+	asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
+	asn_enc_rval_t er;
+	long native, value;
+	asn_per_constraint_t *ct;
+	int inext = 0;
+	asn_INTEGER_enum_map_t key;
+	const asn_INTEGER_enum_map_t *kf;
+
+	if(!sptr) ASN__ENCODE_FAILED;
+	if(!specs) ASN__ENCODE_FAILED;
+
+	if(constraints) ct = &constraints->value;
+	else if(td->per_constraints) ct = &td->per_constraints->value;
+	else ASN__ENCODE_FAILED;	/* Mandatory! */
+
+	ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
+
+	er.encoded = 0;
+
+	native = *(long *)sptr;
+	if(native < 0) ASN__ENCODE_FAILED;
+
+	key.nat_value = native;
+	kf = bsearch(&key, specs->value2enum, specs->map_count,
+		sizeof(key), NativeEnumerated__compar_value2enum);
+	if(!kf) {
+		ASN_DEBUG("No element corresponds to %ld", native);
+		ASN__ENCODE_FAILED;
+	}
+	value = kf - specs->value2enum;
+
+	if(ct->range_bits >= 0) {
+		int cmpWith = specs->extension
+				? specs->extension - 1 : specs->map_count;
+		if(value >= cmpWith)
+			inext = 1;
+	}
+	if(ct->flags & APC_EXTENSIBLE) {
+		if(per_put_few_bits(po, inext, 1))
+			ASN__ENCODE_FAILED;
+		if(inext) ct = 0;
+	} else if(inext) {
+		ASN__ENCODE_FAILED;
+	}
+
+	if(ct && ct->range_bits >= 0) {
+		if(per_put_few_bits(po, value, ct->range_bits))
+			ASN__ENCODE_FAILED;
+		ASN__ENCODED_OK(er);
+	}
+
+	if(!specs->extension)
+		ASN__ENCODE_FAILED;
+
+	/*
+	 * X.691, #10.6: normally small non-negative whole number;
+	 */
+	ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
+		value, specs->extension, inext,
+		value - (inext ? (specs->extension - 1) : 0));
+	if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
+		ASN__ENCODE_FAILED;
+
+	ASN__ENCODED_OK(er);
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/NativeEnumerated.h b/libkmod/pkcs7/asn1c-gen/NativeEnumerated.h
new file mode 100644
index 000000000000..c59bb1ba9438
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/NativeEnumerated.h
@@ -0,0 +1,32 @@
+/*-
+ * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+/*
+ * This type differs from the standard ENUMERATED in that it is modelled using
+ * the fixed machine type (long, int, short), so it can hold only values of
+ * limited length. There is no type (i.e., NativeEnumerated_t, any integer type
+ * will do).
+ * This type may be used when integer range is limited by subtype constraints.
+ */
+#ifndef	_NativeEnumerated_H_
+#define	_NativeEnumerated_H_
+
+#include <NativeInteger.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
+
+xer_type_encoder_f NativeEnumerated_encode_xer;
+per_type_decoder_f NativeEnumerated_decode_uper;
+per_type_encoder_f NativeEnumerated_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _NativeEnumerated_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/NativeInteger.c b/libkmod/pkcs7/asn1c-gen/NativeInteger.c
new file mode 100644
index 000000000000..e8ce6d2c33c1
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/NativeInteger.c
@@ -0,0 +1,332 @@
+/*-
+ * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+/*
+ * Read the NativeInteger.h for the explanation wrt. differences between
+ * INTEGER and NativeInteger.
+ * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
+ * implementation deals with the standard (machine-specific) representation
+ * of them instead of using the platform-independent buffer.
+ */
+#include <asn_internal.h>
+#include <NativeInteger.h>
+
+/*
+ * NativeInteger basic type description.
+ */
+static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
+	"INTEGER",			/* The ASN.1 type is still INTEGER */
+	"INTEGER",
+	NativeInteger_free,
+	NativeInteger_print,
+	asn_generic_no_constraint,
+	NativeInteger_decode_ber,
+	NativeInteger_encode_der,
+	NativeInteger_decode_xer,
+	NativeInteger_encode_xer,
+	NativeInteger_decode_uper,	/* Unaligned PER decoder */
+	NativeInteger_encode_uper,	/* Unaligned PER encoder */
+	0, /* Use generic outmost tag fetcher */
+	asn_DEF_NativeInteger_tags,
+	sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
+	asn_DEF_NativeInteger_tags,	/* Same as above */
+	sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
+/*
+ * Decode INTEGER type.
+ */
+asn_dec_rval_t
+NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td,
+	void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) {
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+	long *native = (long *)*nint_ptr;
+	asn_dec_rval_t rval;
+	ber_tlv_len_t length;
+
+	/*
+	 * If the structure is not there, allocate it.
+	 */
+	if(native == NULL) {
+		native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
+		if(native == NULL) {
+			rval.code = RC_FAIL;
+			rval.consumed = 0;
+			return rval;
+		}
+	}
+
+	ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
+		td->name, tag_mode);
+
+	/*
+	 * Check tags.
+	 */
+	rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
+			tag_mode, 0, &length, 0);
+	if(rval.code != RC_OK)
+		return rval;
+
+	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
+
+	/*
+	 * Make sure we have this length.
+	 */
+	buf_ptr = ((const char *)buf_ptr) + rval.consumed;
+	size -= rval.consumed;
+	if(length > (ber_tlv_len_t)size) {
+		rval.code = RC_WMORE;
+		rval.consumed = 0;
+		return rval;
+	}
+
+	/*
+	 * ASN.1 encoded INTEGER: buf_ptr, length
+	 * Fill the native, at the same time checking for overflow.
+	 * If overflow occured, return with RC_FAIL.
+	 */
+	{
+		INTEGER_t tmp;
+		union {
+			const void *constbuf;
+			void *nonconstbuf;
+		} unconst_buf;
+		long l;
+
+		unconst_buf.constbuf = buf_ptr;
+		tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
+		tmp.size = length;
+
+		if((specs&&specs->field_unsigned)
+			? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
+			: asn_INTEGER2long(&tmp, &l)) {
+			rval.code = RC_FAIL;
+			rval.consumed = 0;
+			return rval;
+		}
+
+		*native = l;
+	}
+
+	rval.code = RC_OK;
+	rval.consumed += length;
+
+	ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
+		(long)rval.consumed, (long)length, td->name, (long)*native);
+
+	return rval;
+}
+
+/*
+ * Encode the NativeInteger using the standard INTEGER type DER encoder.
+ */
+asn_enc_rval_t
+NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr,
+	int tag_mode, ber_tlv_tag_t tag,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	unsigned long native = *(unsigned long *)ptr;	/* Disable sign ext. */
+	asn_enc_rval_t erval;
+	INTEGER_t tmp;
+
+#ifdef	WORDS_BIGENDIAN		/* Opportunistic optimization */
+
+	tmp.buf = (uint8_t *)&native;
+	tmp.size = sizeof(native);
+
+#else	/* Works even if WORDS_BIGENDIAN is not set where should've been */
+	uint8_t buf[sizeof(native)];
+	uint8_t *p;
+
+	/* Prepare a fake INTEGER */
+	for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
+		*p = (uint8_t)native;
+
+	tmp.buf = buf;
+	tmp.size = sizeof(buf);
+#endif	/* WORDS_BIGENDIAN */
+	
+	/* Encode fake INTEGER */
+	erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
+	if(erval.encoded == -1) {
+		assert(erval.structure_ptr == &tmp);
+		erval.structure_ptr = ptr;
+	}
+	return erval;
+}
+
+/*
+ * Decode the chunk of XML text encoding INTEGER.
+ */
+asn_dec_rval_t
+NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
+		const void *buf_ptr, size_t size) {
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+	asn_dec_rval_t rval;
+	INTEGER_t st;
+	void *st_ptr = (void *)&st;
+	long *native = (long *)*sptr;
+
+	if(!native) {
+		native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
+		if(!native) ASN__DECODE_FAILED;
+	}
+
+	memset(&st, 0, sizeof(st));
+	rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr, 
+		opt_mname, buf_ptr, size);
+	if(rval.code == RC_OK) {
+		long l;
+		if((specs&&specs->field_unsigned)
+			? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
+			: asn_INTEGER2long(&st, &l)) {
+			rval.code = RC_FAIL;
+			rval.consumed = 0;
+		} else {
+			*native = l;
+		}
+	} else {
+		/*
+		 * Cannot restart from the middle;
+		 * there is no place to save state in the native type.
+		 * Request a continuation from the very beginning.
+		 */
+		rval.consumed = 0;
+	}
+	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
+	return rval;
+}
+
+
+asn_enc_rval_t
+NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+	char scratch[32];	/* Enough for 64-bit int */
+	asn_enc_rval_t er;
+	const long *native = (const long *)sptr;
+
+	(void)ilevel;
+	(void)flags;
+
+	if(!native) ASN__ENCODE_FAILED;
+
+	er.encoded = snprintf(scratch, sizeof(scratch),
+			(specs && specs->field_unsigned)
+			? "%lu" : "%ld", *native);
+	if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
+		|| cb(scratch, er.encoded, app_key) < 0)
+		ASN__ENCODE_FAILED;
+
+	ASN__ENCODED_OK(er);
+}
+
+asn_dec_rval_t
+NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+	asn_dec_rval_t rval;
+	long *native = (long *)*sptr;
+	INTEGER_t tmpint;
+	void *tmpintptr = &tmpint;
+
+	(void)opt_codec_ctx;
+	ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
+
+	if(!native) {
+		native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
+		if(!native) ASN__DECODE_FAILED;
+	}
+
+	memset(&tmpint, 0, sizeof tmpint);
+	rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
+				   &tmpintptr, pd);
+	if(rval.code == RC_OK) {
+		if((specs&&specs->field_unsigned)
+			? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
+			: asn_INTEGER2long(&tmpint, native))
+			rval.code = RC_FAIL;
+		else
+			ASN_DEBUG("NativeInteger %s got value %ld",
+				td->name, *native);
+	}
+	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
+
+	return rval;
+}
+
+asn_enc_rval_t
+NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+	asn_enc_rval_t er;
+	long native;
+	INTEGER_t tmpint;
+
+	if(!sptr) ASN__ENCODE_FAILED;
+
+	native = *(long *)sptr;
+
+	ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
+
+	memset(&tmpint, 0, sizeof(tmpint));
+	if((specs&&specs->field_unsigned)
+		? asn_ulong2INTEGER(&tmpint, native)
+		: asn_long2INTEGER(&tmpint, native))
+		ASN__ENCODE_FAILED;
+	er = INTEGER_encode_uper(td, constraints, &tmpint, po);
+	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
+	return er;
+}
+
+/*
+ * INTEGER specific human-readable output.
+ */
+int
+NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+	const long *native = (const long *)sptr;
+	char scratch[32];	/* Enough for 64-bit int */
+	int ret;
+
+	(void)td;	/* Unused argument */
+	(void)ilevel;	/* Unused argument */
+
+	if(native) {
+		ret = snprintf(scratch, sizeof(scratch),
+			(specs && specs->field_unsigned)
+			? "%lu" : "%ld", *native);
+		assert(ret > 0 && (size_t)ret < sizeof(scratch));
+		return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
+	} else {
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+	}
+}
+
+void
+NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
+
+	if(!td || !ptr)
+		return;
+
+	ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
+		td->name, contents_only, ptr);
+
+	if(!contents_only) {
+		FREEMEM(ptr);
+	}
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/NativeInteger.h b/libkmod/pkcs7/asn1c-gen/NativeInteger.h
new file mode 100644
index 000000000000..4e63a8355d12
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/NativeInteger.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+/*
+ * This type differs from the standard INTEGER in that it is modelled using
+ * the fixed machine type (long, int, short), so it can hold only values of
+ * limited length. There is no type (i.e., NativeInteger_t, any integer type
+ * will do).
+ * This type may be used when integer range is limited by subtype constraints.
+ */
+#ifndef	_NativeInteger_H_
+#define	_NativeInteger_H_
+
+#include <asn_application.h>
+#include <INTEGER.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern asn_TYPE_descriptor_t asn_DEF_NativeInteger;
+
+asn_struct_free_f  NativeInteger_free;
+asn_struct_print_f NativeInteger_print;
+ber_type_decoder_f NativeInteger_decode_ber;
+der_type_encoder_f NativeInteger_encode_der;
+xer_type_decoder_f NativeInteger_decode_xer;
+xer_type_encoder_f NativeInteger_encode_xer;
+per_type_decoder_f NativeInteger_decode_uper;
+per_type_encoder_f NativeInteger_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _NativeInteger_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c b/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c
new file mode 100644
index 000000000000..d0f8b3117121
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c
@@ -0,0 +1,764 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <INTEGER.h>
+#include <OBJECT_IDENTIFIER.h>
+#include <OCTET_STRING.h>
+#include <limits.h>	/* for CHAR_BIT */
+#include <errno.h>
+
+/*
+ * OBJECT IDENTIFIER basic type description.
+ */
+static const ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (6 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
+	"OBJECT IDENTIFIER",
+	"OBJECT_IDENTIFIER",
+	ASN__PRIMITIVE_TYPE_free,
+	OBJECT_IDENTIFIER_print,
+	OBJECT_IDENTIFIER_constraint,
+	ber_decode_primitive,
+	der_encode_primitive,
+	OBJECT_IDENTIFIER_decode_xer,
+	OBJECT_IDENTIFIER_encode_xer,
+	OCTET_STRING_decode_uper,
+	OCTET_STRING_encode_uper,
+	0, /* Use generic outmost tag fetcher */
+	asn_DEF_OBJECT_IDENTIFIER_tags,
+	sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
+	    / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
+	asn_DEF_OBJECT_IDENTIFIER_tags,	/* Same as above */
+	sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
+	    / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
+
+int
+OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;
+
+	if(st && st->buf) {
+		if(st->size < 1) {
+			ASN__CTFAIL(app_key, td, sptr,
+				"%s: at least one numerical value "
+				"expected (%s:%d)",
+				td->name, __FILE__, __LINE__);
+			return -1;
+		}
+	} else {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: value not given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int
+OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) {
+	unsigned LE GCC_NOTUSED = 1; /* Little endian (x86) */
+	const uint8_t *arcend = arcbuf + arclen;	/* End of arc */
+	unsigned int cache = 0;	/* No more than 14 significant bits */
+	unsigned char *rvbuf = (unsigned char *)rvbufp;
+	unsigned char *rvstart = rvbuf;	/* Original start of the value buffer */
+	int inc;	/* Return value growth direction */
+
+	rvsize *= CHAR_BIT;	/* bytes to bits */
+	arclen *= 7;		/* bytes to bits */
+
+	/*
+	 * The arc has the number of bits
+	 * cannot be represented using supplied return value type.
+	 */
+	if(arclen > rvsize) {
+		if(arclen > (rvsize + CHAR_BIT)) {
+			errno = ERANGE;	/* Overflow */
+			return -1;
+		} else {
+			/*
+			 * Even if the number of bits in the arc representation
+			 * is higher than the width of supplied * return value
+			 * type, there is still possible to fit it when there
+			 * are few unused high bits in the arc value
+			 * representaion.
+			 * 
+			 * Moreover, there is a possibility that the
+			 * number could actually fit the arc space, given
+			 * that add is negative, but we don't handle
+			 * such "temporary lack of precision" situation here.
+			 * May be considered as a bug.
+			 */
+			uint8_t mask = (0xff << (7-(arclen - rvsize))) & 0x7f;
+			if((*arcbuf & mask)) {
+				errno = ERANGE;	/* Overflow */
+				return -1;
+			}
+			/* Fool the routine computing unused bits */
+			arclen -= 7;
+			cache = *arcbuf & 0x7f;
+			arcbuf++;
+		}
+	}
+
+	/* Faster path for common size */
+	if(rvsize == (CHAR_BIT * sizeof(unsigned long))) {
+		unsigned long accum;
+		/* Gather all bits into the accumulator */
+		for(accum = cache; arcbuf < arcend; arcbuf++)
+			accum = (accum << 7) | (*arcbuf & ~0x80);
+		if(accum < (unsigned)-add) {
+			errno = ERANGE;	/* Overflow */
+			return -1;
+		}
+		*(unsigned long *)(void *)rvbuf = accum + add;	/* alignment OK! */
+		return 0;
+	}
+
+#ifndef	WORDS_BIGENDIAN
+	if(*(unsigned char *)&LE) {	/* Little endian (x86) */
+		/* "Convert" to big endian */
+		rvbuf += rvsize / CHAR_BIT - 1;
+		rvstart--;
+		inc = -1;	/* Descending */
+	} else
+#endif	/* !WORDS_BIGENDIAN */
+		inc = +1;	/* Big endian is known [at compile time] */
+
+	{
+		int bits;	/* typically no more than 3-4 bits */
+
+		/* Clear the high unused bits */
+		for(bits = rvsize - arclen;
+			bits > CHAR_BIT;
+				rvbuf += inc, bits -= CHAR_BIT)
+				*rvbuf = 0;
+
+		/* Fill the body of a value */
+		for(; arcbuf < arcend; arcbuf++) {
+			cache = (cache << 7) | (*arcbuf & 0x7f);
+			bits += 7;
+			if(bits >= CHAR_BIT) {
+				bits -= CHAR_BIT;
+				*rvbuf = (cache >> bits);
+				rvbuf += inc;
+			}
+		}
+		if(bits) {
+			*rvbuf = cache;
+			rvbuf += inc;
+		}
+	}
+
+	if(add) {
+		for(rvbuf -= inc; rvbuf != rvstart; rvbuf -= inc) {
+			int v = add + *rvbuf;
+			if(v & ((unsigned)~0 << CHAR_BIT)) {
+				*rvbuf = (unsigned char)(v + (1 << CHAR_BIT));
+				add = -1;
+			} else {
+				*rvbuf = v;
+				break;
+			}
+		}
+		if(rvbuf == rvstart) {
+			/* No space to carry over */
+			errno = ERANGE;	/* Overflow */
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+ssize_t
+OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	char scratch[64];	/* Conservative estimate */
+	unsigned long accum;	/* Bits accumulator */
+	char *p;		/* Position in the scratch buffer */
+
+	if(OBJECT_IDENTIFIER_get_single_arc(arcbuf, arclen, add,
+			&accum, sizeof(accum)))
+		return -1;
+
+	if(accum) {
+		ssize_t len;
+
+		/* Fill the scratch buffer in reverse. */
+		p = scratch + sizeof(scratch);
+		for(; accum; accum /= 10)
+			*(--p) = (char)(accum % 10) + 0x30; /* Put a digit */
+
+		len = sizeof(scratch) - (p - scratch);
+		if(cb(p, len, app_key) < 0)
+			return -1;
+		return len;
+	} else {
+		*scratch = 0x30;
+		if(cb(scratch, 1, app_key) < 0)
+			return -1;
+		return 1;
+	}
+}
+
+int
+OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen, int add,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+
+	if(OBJECT_IDENTIFIER__dump_arc(arcbuf, arclen, add, cb, app_key) < 0)
+		return -1;
+
+	return 0;
+}
+
+static ssize_t
+OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st, asn_app_consume_bytes_f *cb, void *app_key) {
+	ssize_t wrote_len = 0;
+	int startn;
+	int add = 0;
+	int i;
+
+	for(i = 0, startn = 0; i < st->size; i++) {
+		uint8_t b = st->buf[i];
+		if((b & 0x80))			/* Continuation expected */
+			continue;
+
+		if(startn == 0) {
+			/*
+			 * First two arcs are encoded through the backdoor.
+			 */
+			if(i) {
+				add = -80;
+				if(cb("2", 1, app_key) < 0) return -1;
+			} else if(b <= 39) {
+				add = 0;
+				if(cb("0", 1, app_key) < 0) return -1;
+			} else if(b < 79) {
+				add = -40;
+				if(cb("1", 1, app_key) < 0) return -1;
+			} else {
+				add = -80;
+				if(cb("2", 1, app_key) < 0) return -1;
+			}
+			wrote_len += 1;
+		}
+
+		if(cb(".", 1, app_key) < 0)	/* Separate arcs */
+			return -1;
+
+		add = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn],
+				i - startn + 1, add, cb, app_key);
+		if(add < 0) return -1;
+		wrote_len += 1 + add;
+		startn = i + 1;
+		add = 0;
+	}
+
+	return wrote_len;
+}
+
+static enum xer_pbd_rval
+OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
+	OBJECT_IDENTIFIER_t *st = (OBJECT_IDENTIFIER_t *)sptr;
+	const char *chunk_end = (const char *)chunk_buf + chunk_size;
+	const char *endptr;
+	long s_arcs[10];
+	long *arcs = s_arcs;
+	int arcs_count;
+	int ret;
+
+	(void)td;
+
+	arcs_count = OBJECT_IDENTIFIER_parse_arcs(
+		(const char *)chunk_buf, chunk_size, arcs,
+			sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
+	if(arcs_count < 0) {
+		/* Expecting more than zero arcs */
+		return XPBD_BROKEN_ENCODING;
+	} else if(arcs_count == 0) {
+		return XPBD_NOT_BODY_IGNORE;
+	}
+	assert(endptr == chunk_end);
+
+	if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
+		arcs = (long *)MALLOC(arcs_count * sizeof(long));
+		if(!arcs) return XPBD_SYSTEM_FAILURE;
+		ret = OBJECT_IDENTIFIER_parse_arcs(
+			(const char *)chunk_buf, chunk_size,
+			arcs, arcs_count, &endptr);
+		if(ret != arcs_count)
+			return XPBD_SYSTEM_FAILURE;	/* assert?.. */
+	}
+
+	/*
+	 * Convert arcs into BER representation.
+	 */
+	ret = OBJECT_IDENTIFIER_set_arcs(st, arcs, sizeof(*arcs), arcs_count);
+	if(arcs != s_arcs) FREEMEM(arcs);
+
+	return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
+}
+
+asn_dec_rval_t
+OBJECT_IDENTIFIER_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
+		const void *buf_ptr, size_t size) {
+
+	return xer_decode_primitive(opt_codec_ctx, td,
+		sptr, sizeof(OBJECT_IDENTIFIER_t), opt_mname,
+			buf_ptr, size, OBJECT_IDENTIFIER__xer_body_decode);
+}
+
+asn_enc_rval_t
+OBJECT_IDENTIFIER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;
+	asn_enc_rval_t er;
+
+	(void)ilevel;
+	(void)flags;
+
+	if(!st || !st->buf)
+		ASN__ENCODE_FAILED;
+
+	er.encoded = OBJECT_IDENTIFIER__dump_body(st, cb, app_key);
+	if(er.encoded < 0) ASN__ENCODE_FAILED;
+
+	ASN__ENCODED_OK(er);
+}
+
+int
+OBJECT_IDENTIFIER_print(asn_TYPE_descriptor_t *td, const void *sptr,
+	int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
+	const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;
+
+	(void)td;	/* Unused argument */
+	(void)ilevel;	/* Unused argument */
+
+	if(!st || !st->buf)
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+
+	/* Dump preamble */
+	if(cb("{ ", 2, app_key) < 0)
+		return -1;
+
+	if(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0)
+		return -1;
+
+	return (cb(" }", 2, app_key) < 0) ? -1 : 0;
+}
+
+int
+OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *oid, void *arcs,
+		unsigned int arc_type_size, unsigned int arc_slots) {
+	void *arcs_end = (char *)arcs + (arc_type_size * arc_slots);
+	int num_arcs = 0;
+	int startn = 0;
+	int add = 0;
+	int i;
+
+	if(!oid || !oid->buf || (arc_slots && arc_type_size <= 1)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	for(i = 0; i < oid->size; i++) {
+		uint8_t b = oid->buf[i];
+		if((b & 0x80))			/* Continuation expected */
+			continue;
+
+		if(num_arcs == 0) {
+			/*
+			 * First two arcs are encoded through the backdoor.
+			 */
+			unsigned LE = 1;	/* Little endian */
+			int first_arc;
+			num_arcs++;
+			if(!arc_slots) { num_arcs++; continue; }
+
+			if(i) first_arc = 2;
+			else if(b <= 39) first_arc = 0;
+			else if(b < 79)	first_arc = 1;
+			else first_arc = 2;
+
+			add = -40 * first_arc;
+			memset(arcs, 0, arc_type_size);
+			*(unsigned char *)((char *)arcs
+				+ ((*(char *)&LE)?0:(arc_type_size - 1)))
+					= first_arc;
+			arcs = ((char *)arcs) + arc_type_size;
+		}
+
+		/* Decode, if has space */
+		if(arcs < arcs_end) {
+			if(OBJECT_IDENTIFIER_get_single_arc(&oid->buf[startn],
+				i - startn + 1, add,
+					arcs, arc_type_size))
+				return -1;
+			startn = i + 1;
+			arcs = ((char *)arcs) + arc_type_size;
+			add = 0;
+		}
+		num_arcs++;
+	}
+
+	return num_arcs;
+}
+
+
+/*
+ * Save the single value as an object identifier arc.
+ */
+int
+OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, const void *arcval, unsigned int arcval_size, int prepared_order) {
+	/*
+	 * The following conditions must hold:
+	 * assert(arcval);
+	 * assert(arcval_size > 0);
+	 * assert(arcval_size <= 16);
+	 * assert(arcbuf);
+	 */
+#ifdef	WORDS_BIGENDIAN
+	const unsigned isLittleEndian = 0;
+#else
+	unsigned LE = 1;
+	unsigned isLittleEndian = *(char *)&LE;
+#endif
+	const uint8_t *tend, *tp;
+	unsigned int cache;
+	uint8_t *bp = arcbuf;
+	int bits;
+	uint8_t buffer[16];
+
+	if(isLittleEndian && !prepared_order) {
+		const uint8_t *a = (const unsigned char *)arcval + arcval_size - 1;
+		const uint8_t *aend = (const uint8_t *)arcval;
+		uint8_t *msb = buffer + arcval_size - 1;
+		uint8_t *tb;
+		for(tb = buffer; a >= aend; tb++, a--)
+			if((*tb = *a) && (tb < msb))
+				msb = tb;
+		tend = &buffer[arcval_size];
+		tp = msb;	/* Most significant non-zero byte */
+	} else {
+		/* Look for most significant non-zero byte */
+		tend = (const unsigned char *)arcval + arcval_size;
+		for(tp = (const uint8_t *)arcval; tp < tend - 1; tp++)
+			if(*tp) break;
+	}
+
+	/*
+	 * Split the value in 7-bits chunks.
+	 */
+	bits = ((tend - tp) * CHAR_BIT) % 7;
+	if(bits) {
+		cache = *tp >> (CHAR_BIT - bits);
+		if(cache) {
+			*bp++ = cache | 0x80;
+			cache = *tp++;
+			bits = CHAR_BIT - bits;
+		} else {
+			bits = -bits;
+		}
+	} else {
+		cache = 0;
+	}
+	for(; tp < tend; tp++) {
+		cache = (cache << CHAR_BIT) + *tp;
+		bits += CHAR_BIT;
+		while(bits >= 7) {
+			bits -= 7;
+			*bp++ = 0x80 | (cache >> bits);
+		}
+	}
+	if(bits) *bp++ = cache;
+	bp[-1] &= 0x7f;	/* Clear the last bit */
+
+	return bp - arcbuf;
+}
+
+int
+OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid, const void *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
+	uint8_t *buf;
+	uint8_t *bp;
+	unsigned LE = 1;	/* Little endian (x86) */
+	unsigned isLittleEndian = *((char *)&LE);
+	unsigned int arc0;
+	unsigned int arc1;
+	unsigned size;
+	unsigned i;
+
+	if(!oid || !arcs || arc_type_size < 1
+	|| arc_type_size > 16
+	|| arc_slots < 2) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	switch(arc_type_size) {
+	case sizeof(char):
+		arc0 = ((const unsigned char *)arcs)[0];
+		arc1 = ((const unsigned char *)arcs)[1];
+		break;
+	case sizeof(short):
+		arc0 = ((const unsigned short *)arcs)[0];
+		arc1 = ((const unsigned short *)arcs)[1];
+		break;
+	case sizeof(int):
+		arc0 = ((const unsigned int *)arcs)[0];
+		arc1 = ((const unsigned int *)arcs)[1];
+		break;
+	default:
+		arc1 = arc0 = 0;
+		if(isLittleEndian) {	/* Little endian (x86) */
+			const unsigned char *ps, *pe;
+			/* If more significant bytes are present,
+			 * make them > 255 quick */
+			for(ps = (const unsigned char *)arcs + 1, pe = ps+arc_type_size;
+					ps < pe; ps++)
+				arc0 |= *ps, arc1 |= *(ps + arc_type_size);
+			arc0 <<= CHAR_BIT, arc1 <<= CHAR_BIT;
+			arc0 = *((const unsigned char *)arcs + 0);
+			arc1 = *((const unsigned char *)arcs + arc_type_size);
+		} else {
+			const unsigned char *ps, *pe;
+			/* If more significant bytes are present,
+			 * make them > 255 quick */
+			for(ps = (const unsigned char *)arcs, pe = ps+arc_type_size - 1; ps < pe; ps++)
+				arc0 |= *ps, arc1 |= *(ps + arc_type_size);
+			arc0 = *((const unsigned char *)arcs + arc_type_size - 1);
+			arc1 = *((const unsigned char *)arcs +(arc_type_size<< 1)-1);
+		}
+	}
+
+	/*
+	 * The previous chapter left us with the first and the second arcs.
+	 * The values are not precise (that is, they are valid only if
+	 * they're less than 255), but OK for the purposes of making
+	 * the sanity test below.
+	 */
+	if(arc0 <= 1) {
+		if(arc1 >= 39) {
+			/* 8.19.4: At most 39 subsequent values (including 0) */
+			errno = ERANGE;
+			return -1;
+		}
+	} else if(arc0 > 2) {
+		/* 8.19.4: Only three values are allocated from the root node */
+		errno = ERANGE;
+		return -1;
+	}
+	/*
+	 * After above tests it is known that the value of arc0 is completely
+	 * trustworthy (0..2). However, the arc1's value is still meaningless.
+	 */
+
+	/*
+	 * Roughly estimate the maximum size necessary to encode these arcs.
+	 * This estimation implicitly takes in account the following facts,
+	 * that cancel each other:
+	 * 	* the first two arcs are encoded in a single value.
+	 * 	* the first value may require more space (+1 byte)
+	 * 	* the value of the first arc which is in range (0..2)
+	 */
+	size = ((arc_type_size * CHAR_BIT + 6) / 7) * arc_slots;
+	bp = buf = (uint8_t *)MALLOC(size + 1);
+	if(!buf) {
+		/* ENOMEM */
+		return -1;
+	}
+
+	/*
+	 * Encode the first two arcs.
+	 * These require special treatment.
+	 */
+	{
+		uint8_t *tp;
+		uint8_t first_value[1 + 16];	/* of two arcs */
+		uint8_t *fv = first_value;
+
+		/*
+		 * Simulate first_value = arc0 * 40 + arc1;
+		 */
+		/* Copy the second (1'st) arcs[1] into the first_value */
+		*fv++ = 0;
+		arcs = ((const char *)arcs) + arc_type_size;
+		if(isLittleEndian) {
+			const uint8_t *aend = (const unsigned char *)arcs - 1;
+			const uint8_t *a1 = (const unsigned char *)arcs + arc_type_size - 1;
+			for(; a1 > aend; fv++, a1--) *fv = *a1;
+		} else {
+			const uint8_t *a1 = (const uint8_t *)arcs;
+			const uint8_t *aend = a1 + arc_type_size;
+			for(; a1 < aend; fv++, a1++) *fv = *a1;
+		}
+		/* Increase the first_value by arc0 */
+		arc0 *= 40;	/* (0..80) */
+		for(tp = first_value + arc_type_size; tp >= first_value; tp--) {
+			unsigned int v = *tp;
+			v += arc0;
+			*tp = v;
+			if(v >= (1 << CHAR_BIT)) arc0 = v >> CHAR_BIT;
+			else break;
+		}
+
+		assert(tp >= first_value);
+
+		bp += OBJECT_IDENTIFIER_set_single_arc(bp, first_value,
+			fv - first_value, 1);
+ 	}
+
+	/*
+	 * Save the rest of arcs.
+	 */
+	for(arcs = ((const char *)arcs) + arc_type_size, i = 2;
+		i < arc_slots;
+			i++, arcs = ((const char *)arcs) + arc_type_size) {
+		bp += OBJECT_IDENTIFIER_set_single_arc(bp,
+			arcs, arc_type_size, 0);
+	}
+
+	assert((unsigned)(bp - buf) <= size);
+
+	/*
+	 * Replace buffer.
+	 */
+	oid->size = bp - buf;
+	bp = oid->buf;
+	oid->buf = buf;
+	if(bp) FREEMEM(bp);
+
+	return 0;
+}
+
+
+int
+OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
+	long *arcs, unsigned int arcs_slots, const char **opt_oid_text_end) {
+	unsigned int arcs_count = 0;
+	const char *oid_end;
+	enum {
+		ST_LEADSPACE,
+		ST_TAILSPACE,
+		ST_AFTERVALUE,	/* Next character ought to be '.' or a space */
+		ST_WAITDIGITS 	/* Next character is expected to be a digit */
+	} state = ST_LEADSPACE;
+
+	if(!oid_text || oid_txt_length < -1 || (arcs_slots && !arcs)) {
+		if(opt_oid_text_end) *opt_oid_text_end = oid_text;
+		errno = EINVAL;
+		return -1;
+	}
+
+	if(oid_txt_length == -1)
+		oid_txt_length = strlen(oid_text);
+
+#define	_OID_CAPTURE_ARC(oid_text, oid_end)		do {	\
+	const char *endp = oid_end;				\
+	long value;						\
+	switch(asn_strtol_lim(oid_text, &endp, &value)) {	\
+	case ASN_STRTOL_EXTRA_DATA:				\
+	case ASN_STRTOL_OK:					\
+		if(arcs_count < arcs_slots)			\
+			arcs[arcs_count] = value;		\
+		arcs_count++;					\
+		oid_text = endp - 1;				\
+		break;						\
+	case ASN_STRTOL_ERROR_RANGE:				\
+		if(opt_oid_text_end)				\
+			*opt_oid_text_end = oid_text;		\
+		errno = ERANGE;					\
+		return -1;					\
+	case ASN_STRTOL_ERROR_INVAL:				\
+	case ASN_STRTOL_EXPECT_MORE:				\
+		if(opt_oid_text_end)				\
+			*opt_oid_text_end = oid_text;		\
+		errno = EINVAL;					\
+		return -1;					\
+	}							\
+  } while(0)
+
+	for(oid_end = oid_text + oid_txt_length; oid_text<oid_end; oid_text++) {
+	    switch(*oid_text) {
+	    case 0x09: case 0x0a: case 0x0d: case 0x20:	/* whitespace */
+		switch(state) {
+		case ST_LEADSPACE:
+		case ST_TAILSPACE:
+			continue;
+		case ST_AFTERVALUE:
+			state = ST_TAILSPACE;
+			continue;
+		case ST_WAITDIGITS:
+			break;	/* Digits expected after ".", got whitespace */
+		}
+		break;
+	    case 0x2e:	/* '.' */
+		switch(state) {
+		case ST_LEADSPACE:
+		case ST_TAILSPACE:
+		case ST_WAITDIGITS:
+			if(opt_oid_text_end)
+				*opt_oid_text_end = oid_text;
+			errno = EINVAL;	/* Broken OID */
+			return -1;
+			break;
+		case ST_AFTERVALUE:
+			state = ST_WAITDIGITS;
+			continue;
+		}
+		break;
+	    case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
+	    case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
+		switch(state) {
+		case ST_TAILSPACE:
+		case ST_AFTERVALUE:
+			if(opt_oid_text_end)
+				*opt_oid_text_end = oid_text;
+			errno = EINVAL;	/* "1. 1" => broken OID */
+			return -1;
+		case ST_LEADSPACE:
+		case ST_WAITDIGITS:
+			_OID_CAPTURE_ARC(oid_text, oid_end);
+			state = ST_AFTERVALUE;
+			continue;
+		}
+		break;
+	    default:
+		/* Unexpected symbols */
+		state = ST_WAITDIGITS;
+		break;
+	    } /* switch() */
+	    break;
+	} /* for() */
+
+
+	if(opt_oid_text_end) *opt_oid_text_end = oid_text;
+
+	/* Finalize last arc */
+	switch(state) {
+	case ST_LEADSPACE:
+		return 0; /* No OID found in input data */
+	case ST_WAITDIGITS:
+		errno = EINVAL;	/* Broken OID */
+		return -1;
+	case ST_AFTERVALUE:
+	case ST_TAILSPACE:
+		return arcs_count;
+	}
+
+	errno = EINVAL;	/* Broken OID */
+	return -1;
+}
+
+
diff --git a/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h b/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h
new file mode 100644
index 000000000000..c2c6373e3bc2
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h
@@ -0,0 +1,139 @@
+/*-
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * 	All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_OBJECT_IDENTIFIER_H_
+#define	_OBJECT_IDENTIFIER_H_
+
+#include <asn_application.h>
+#include <asn_codecs_prim.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef ASN__PRIMITIVE_TYPE_t OBJECT_IDENTIFIER_t;
+
+extern asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER;
+
+asn_struct_print_f OBJECT_IDENTIFIER_print;
+asn_constr_check_f OBJECT_IDENTIFIER_constraint;
+der_type_encoder_f OBJECT_IDENTIFIER_encode_der;
+xer_type_decoder_f OBJECT_IDENTIFIER_decode_xer;
+xer_type_encoder_f OBJECT_IDENTIFIER_encode_xer;
+
+/**********************************
+ * Some handy conversion routines *
+ **********************************/
+
+/*
+ * This function fills an (_arcs) array with OBJECT IDENTIFIER arcs
+ * up to specified (_arc_slots) elements.
+ * 
+ * EXAMPLE:
+ * 	void print_arcs(OBJECT_IDENTIFIER_t *oid) {
+ * 		unsigned long fixed_arcs[10];	// Try with fixed space first
+ * 		unsigned long *arcs = fixed_arcs;
+ * 		int arc_type_size = sizeof(fixed_arcs[0]);	// sizeof(long)
+ * 		int arc_slots = sizeof(fixed_arcs)/sizeof(fixed_arcs[0]); // 10
+ * 		int count;	// Real number of arcs.
+ * 		int i;
+ * 
+ * 		count = OBJECT_IDENTIFIER_get_arcs(oid, arcs,
+ * 			arc_type_size, arc_slots);
+ * 		// If necessary, reallocate arcs array and try again.
+ * 		if(count > arc_slots) {
+ * 			arc_slots = count;
+ * 			arcs = malloc(arc_type_size * arc_slots);
+ * 			if(!arcs) return;
+ * 			count = OBJECT_IDENTIFIER_get_arcs(oid, arcs,
+ * 				arc_type_size, arc_slots);
+ * 			assert(count == arc_slots);
+ * 		}
+ * 
+ * 		// Print the contents of the arcs array.
+ * 		for(i = 0; i < count; i++)
+ * 			printf("%d\n", arcs[i]);
+ * 
+ * 		// Avoid memory leak.
+ * 		if(arcs != fixed_arcs) free(arcs);
+ * 	}
+ * 
+ * RETURN VALUES:
+ * -1/EINVAL:	Invalid arguments (oid is missing)
+ * -1/ERANGE:	One or more arcs have value out of array cell type range.
+ * >=0:		Number of arcs contained in the OBJECT IDENTIFIER
+ * 
+ * WARNING: The function always returns the real number of arcs,
+ * even if there is no sufficient (_arc_slots) provided.
+ */
+int OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *_oid,
+	void *_arcs,			/* e.g., unsigned int arcs[N] */
+	unsigned int _arc_type_size,	/* e.g., sizeof(arcs[0]) */
+	unsigned int _arc_slots		/* e.g., N */);
+
+/*
+ * This functions initializes the OBJECT IDENTIFIER object with
+ * the given set of arcs.
+ * The minimum of two arcs must be present; some restrictions apply.
+ * RETURN VALUES:
+ * -1/EINVAL:	Invalid arguments
+ * -1/ERANGE:	The first two arcs do not conform to ASN.1 restrictions.
+ * -1/ENOMEM:	Memory allocation failed
+ * 0:		The object was initialized with new arcs.
+ */
+int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *_oid,
+	const void *_arcs,		/* e.g., unsigned int arcs[N] */
+	unsigned int _arc_type_size,	/* e.g., sizeof(arcs[0]) */
+	unsigned int _arc_slots		/* e.g., N */);
+
+/*
+ * Print the specified OBJECT IDENTIFIER arc.
+ */
+int OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen,
+	int add, /* Arbitrary offset, required to process the first two arcs */
+	asn_app_consume_bytes_f *cb, void *app_key);
+
+/* Same as above, but returns the number of written digits, instead of 0 */
+ssize_t OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add,
+	asn_app_consume_bytes_f *cb, void *app_key);
+
+/*
+ * Parse the OBJECT IDENTIFIER textual representation ("1.3.6.1.4.1.9363").
+ * No arc can exceed the (0..signed_long_max) range (typically, 0..2G if L32).
+ * This function is not specific to OBJECT IDENTIFIER, it may be used to parse
+ * the RELATIVE-OID data, or any other data consisting of dot-separated
+ * series of numeric values.
+ *
+ * If (oid_txt_length == -1), the strlen() will be invoked to determine the
+ * size of the (oid_text) string.
+ * 
+ * After return, the optional (opt_oid_text_end) is set to the character after
+ * the last parsed one. (opt_oid_text_end) is never less than (oid_text).
+ * 
+ * RETURN VALUES:
+ *   -1:	Parse error.
+ * >= 0:	Number of arcs contained in the OBJECT IDENTIFIER.
+ * 
+ * WARNING: The function always returns the real number of arcs,
+ * even if there is no sufficient (_arc_slots) provided.
+ * This is useful for (_arc_slots) value estimation.
+ */
+int OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
+	long arcs[], unsigned int arcs_slots, const char **opt_oid_text_end);
+
+/*
+ * Internal functions.
+ * Used by RELATIVE-OID implementation in particular.
+ */
+int OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned int arclen,
+	signed int add, void *value, unsigned int value_size);
+int OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf,
+	const void *arcval, unsigned int arcval_size, int _prepared_order);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _OBJECT_IDENTIFIER_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/OCTET_STRING.c b/libkmod/pkcs7/asn1c-gen/OCTET_STRING.c
new file mode 100644
index 000000000000..5420dedecab2
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/OCTET_STRING.c
@@ -0,0 +1,1807 @@
+/*-
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <OCTET_STRING.h>
+#include <BIT_STRING.h>	/* for .bits_unused member */
+#include <errno.h>
+
+/*
+ * OCTET STRING basic type description.
+ */
+static const ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
+};
+static const asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = {
+	sizeof(OCTET_STRING_t),
+	offsetof(OCTET_STRING_t, _asn_ctx),
+	ASN_OSUBV_STR
+};
+static const asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = {
+	{ APC_CONSTRAINED, 8, 8, 0, 255 },
+	{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
+	0, 0
+};
+asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
+	"OCTET STRING",		/* Canonical name */
+	"OCTET_STRING",		/* XML tag name */
+	OCTET_STRING_free,
+	OCTET_STRING_print,	/* non-ascii stuff, generally */
+	asn_generic_no_constraint,
+	OCTET_STRING_decode_ber,
+	OCTET_STRING_encode_der,
+	OCTET_STRING_decode_xer_hex,
+	OCTET_STRING_encode_xer,
+	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
+	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
+	0, /* Use generic outmost tag fetcher */
+	asn_DEF_OCTET_STRING_tags,
+	sizeof(asn_DEF_OCTET_STRING_tags)
+	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
+	asn_DEF_OCTET_STRING_tags,	/* Same as above */
+	sizeof(asn_DEF_OCTET_STRING_tags)
+	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	&asn_DEF_OCTET_STRING_specs
+};
+
+#undef	_CH_PHASE
+#undef	NEXT_PHASE
+#undef	PREV_PHASE
+#define	_CH_PHASE(ctx, inc) do {					\
+		if(ctx->phase == 0)					\
+			ctx->context = 0;				\
+		ctx->phase += inc;					\
+	} while(0)
+#define	NEXT_PHASE(ctx)	_CH_PHASE(ctx, +1)
+#define	PREV_PHASE(ctx)	_CH_PHASE(ctx, -1)
+
+#undef	ADVANCE
+#define	ADVANCE(num_bytes)	do {					\
+		size_t num = (num_bytes);				\
+		buf_ptr = ((const char *)buf_ptr) + num;		\
+		size -= num;						\
+		consumed_myself += num;					\
+	} while(0)
+
+#undef	RETURN
+#define	RETURN(_code)	do {						\
+		asn_dec_rval_t tmprval;					\
+		tmprval.code = _code;					\
+		tmprval.consumed = consumed_myself;			\
+		return tmprval;						\
+	} while(0)
+
+#undef	APPEND
+#define	APPEND(bufptr, bufsize)	do {					\
+		size_t _bs = (bufsize);		/* Append size */	\
+		size_t _ns = ctx->context;	/* Allocated now */	\
+		size_t _es = st->size + _bs;	/* Expected size */	\
+		/* int is really a typeof(st->size): */			\
+		if((int)_es < 0) RETURN(RC_FAIL);			\
+		if(_ns <= _es) {					\
+			void *ptr;					\
+			/* Be nice and round to the memory allocator */	\
+			do { _ns = _ns ? _ns << 1 : 16; }		\
+			    while(_ns <= _es);				\
+			/* int is really a typeof(st->size): */		\
+			if((int)_ns < 0) RETURN(RC_FAIL);		\
+			ptr = REALLOC(st->buf, _ns);			\
+			if(ptr) {					\
+				st->buf = (uint8_t *)ptr;		\
+				ctx->context = _ns;			\
+			} else {					\
+				RETURN(RC_FAIL);			\
+			}						\
+			ASN_DEBUG("Reallocating into %ld", (long)_ns);	\
+		}							\
+		memcpy(st->buf + st->size, bufptr, _bs);		\
+		/* Convenient nul-termination */			\
+		st->buf[_es] = '\0';					\
+		st->size = _es;						\
+	} while(0)
+
+/*
+ * The main reason why ASN.1 is still alive is that too much time and effort
+ * is necessary for learning it more or less adequately, thus creating a gut
+ * necessity to demonstrate that aquired skill everywhere afterwards.
+ * No, I am not going to explain what the following stuff is.
+ */
+struct _stack_el {
+	ber_tlv_len_t	left;	/* What's left to read (or -1) */
+	ber_tlv_len_t	got;	/* What was actually processed */
+	int	cont_level;	/* Depth of subcontainment */
+	int	want_nulls;	/* Want null "end of content" octets? */
+	int	bits_chopped;	/* Flag in BIT STRING mode */
+	ber_tlv_tag_t	tag;	/* For debugging purposes */
+	struct _stack_el *prev;
+	struct _stack_el *next;
+};
+struct _stack {
+	struct _stack_el *tail;
+	struct _stack_el *cur_ptr;
+};
+
+static struct _stack_el *
+OS__add_stack_el(struct _stack *st) {
+	struct _stack_el *nel;
+
+	/*
+	 * Reuse the old stack frame or allocate a new one.
+	 */
+	if(st->cur_ptr && st->cur_ptr->next) {
+		nel = st->cur_ptr->next;
+		nel->bits_chopped = 0;
+		nel->got = 0;
+		/* Retain the nel->cont_level, it's correct. */
+	} else {
+		nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el));
+		if(nel == NULL)
+			return NULL;
+	
+		if(st->tail) {
+			/* Increase a subcontainment depth */
+			nel->cont_level = st->tail->cont_level + 1;
+			st->tail->next = nel;
+		}
+		nel->prev = st->tail;
+		st->tail = nel;
+	}
+
+	st->cur_ptr = nel;
+
+	return nel;
+}
+
+static struct _stack *
+_new_stack() {
+	return (struct _stack *)CALLOC(1, sizeof(struct _stack));
+}
+
+/*
+ * Decode OCTET STRING type.
+ */
+asn_dec_rval_t
+OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td,
+	void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
+	asn_OCTET_STRING_specifics_t *specs = td->specifics
+				? (asn_OCTET_STRING_specifics_t *)td->specifics
+				: &asn_DEF_OCTET_STRING_specs;
+	BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
+	asn_dec_rval_t rval;
+	asn_struct_ctx_t *ctx;
+	ssize_t consumed_myself = 0;
+	struct _stack *stck;		/* Expectations stack structure */
+	struct _stack_el *sel = 0;	/* Stack element */
+	int tlv_constr;
+	enum asn_OS_Subvariant type_variant = specs->subvariant;
+
+	ASN_DEBUG("Decoding %s as %s (frame %ld)",
+		td->name,
+		(type_variant == ASN_OSUBV_STR) ?
+			"OCTET STRING" : "OS-SpecialCase",
+		(long)size);
+
+	/*
+	 * Create the string if does not exist.
+	 */
+	if(st == NULL) {
+		st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
+		if(st == NULL) RETURN(RC_FAIL);
+	}
+
+	/* Restore parsing context */
+	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
+
+	switch(ctx->phase) {
+	case 0:
+		/*
+		 * Check tags.
+		 */
+		rval = ber_check_tags(opt_codec_ctx, td, ctx,
+			buf_ptr, size, tag_mode, -1,
+			&ctx->left, &tlv_constr);
+		if(rval.code != RC_OK)
+			return rval;
+
+		if(tlv_constr) {
+			/*
+			 * Complex operation, requires stack of expectations.
+			 */
+			ctx->ptr = _new_stack();
+			if(ctx->ptr) {
+				stck = (struct _stack *)ctx->ptr;
+			} else {
+				RETURN(RC_FAIL);
+			}
+		} else {
+			/*
+			 * Jump into stackless primitive decoding.
+			 */
+			_CH_PHASE(ctx, 3);
+			if(type_variant == ASN_OSUBV_ANY && tag_mode != 1)
+				APPEND(buf_ptr, rval.consumed);
+			ADVANCE(rval.consumed);
+			goto phase3;
+		}
+
+		NEXT_PHASE(ctx);
+		/* Fall through */
+	case 1:
+	phase1:
+		/*
+		 * Fill the stack with expectations.
+		 */
+		stck = (struct _stack *)ctx->ptr;
+		sel = stck->cur_ptr;
+	  do {
+		ber_tlv_tag_t tlv_tag;
+		ber_tlv_len_t tlv_len;
+		ber_tlv_tag_t expected_tag;
+		ssize_t tl, ll, tlvl;
+				/* This one works even if (sel->left == -1) */
+		ssize_t Left = ((!sel||(size_t)sel->left >= size)
+					?(ssize_t)size:sel->left);
+
+
+		ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", sel,
+			(long)(sel?sel->left:0),
+			(long)(sel?sel->want_nulls:0),
+			(long)(sel?sel->got:0)
+		);
+		if(sel && sel->left <= 0 && sel->want_nulls == 0) {
+			if(sel->prev) {
+				struct _stack_el *prev = sel->prev;
+				if(prev->left != -1) {
+					if(prev->left < sel->got)
+						RETURN(RC_FAIL);
+					prev->left -= sel->got;
+				}
+				prev->got += sel->got;
+				sel = stck->cur_ptr = prev;
+				if(!sel) break;
+				tlv_constr = 1;
+				continue;
+			} else {
+				sel = stck->cur_ptr = 0;
+				break;	/* Nothing to wait */
+			}
+		}
+
+		tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag);
+		ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld",
+			(long)size, (long)Left, sel?"":"!",
+			(long)(sel?sel->left:0),
+			(long)(sel?sel->want_nulls:0),
+			(long)tl);
+		switch(tl) {
+		case -1: RETURN(RC_FAIL);
+		case 0: RETURN(RC_WMORE);
+		}
+
+		tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
+
+		ll = ber_fetch_length(tlv_constr,
+				(const char *)buf_ptr + tl,Left - tl,&tlv_len);
+		ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld",
+			ber_tlv_tag_string(tlv_tag), tlv_constr,
+				(long)Left, (long)tl, (long)tlv_len, (long)ll);
+		switch(ll) {
+		case -1: RETURN(RC_FAIL);
+		case 0: RETURN(RC_WMORE);
+		}
+
+		if(sel && sel->want_nulls
+			&& ((const uint8_t *)buf_ptr)[0] == 0
+			&& ((const uint8_t *)buf_ptr)[1] == 0)
+		{
+
+			ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
+
+			if(type_variant == ASN_OSUBV_ANY
+			&& (tag_mode != 1 || sel->cont_level))
+				APPEND("\0\0", 2);
+
+			ADVANCE(2);
+			sel->got += 2;
+			if(sel->left != -1) {
+				sel->left -= 2;	/* assert(sel->left >= 2) */
+			}
+
+			sel->want_nulls--;
+			if(sel->want_nulls == 0) {
+				/* Move to the next expectation */
+				sel->left = 0;
+				tlv_constr = 1;
+			}
+
+			continue;
+		}
+
+		/*
+		 * Set up expected tags,
+		 * depending on ASN.1 type being decoded.
+		 */
+		switch(type_variant) {
+		case ASN_OSUBV_BIT:
+			/* X.690: 8.6.4.1, NOTE 2 */
+			/* Fall through */
+		case ASN_OSUBV_STR:
+		default:
+			if(sel) {
+				int level = sel->cont_level;
+				if(level < td->all_tags_count) {
+					expected_tag = td->all_tags[level];
+					break;
+				} else if(td->all_tags_count) {
+					expected_tag = td->all_tags
+						[td->all_tags_count - 1];
+					break;
+				}
+				/* else, Fall through */
+			}
+			/* Fall through */
+		case ASN_OSUBV_ANY:
+			expected_tag = tlv_tag;
+			break;
+		}
+
+
+		if(tlv_tag != expected_tag) {
+			char buf[2][32];
+			ber_tlv_tag_snprint(tlv_tag,
+				buf[0], sizeof(buf[0]));
+			ber_tlv_tag_snprint(td->tags[td->tags_count-1],
+				buf[1], sizeof(buf[1]));
+			ASN_DEBUG("Tag does not match expectation: %s != %s",
+				buf[0], buf[1]);
+			RETURN(RC_FAIL);
+		}
+
+		tlvl = tl + ll;	/* Combined length of T and L encoding */
+		if((tlv_len + tlvl) < 0) {
+			/* tlv_len value is too big */
+			ASN_DEBUG("TLV encoding + length (%ld) is too big",
+				(long)tlv_len);
+			RETURN(RC_FAIL);
+		}
+
+		/*
+		 * Append a new expectation.
+		 */
+		sel = OS__add_stack_el(stck);
+		if(!sel) RETURN(RC_FAIL);
+
+		sel->tag = tlv_tag;
+
+		sel->want_nulls = (tlv_len==-1);
+		if(sel->prev && sel->prev->left != -1) {
+			/* Check that the parent frame is big enough */
+			if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len))
+				RETURN(RC_FAIL);
+			if(tlv_len == -1)
+				sel->left = sel->prev->left - tlvl;
+			else
+				sel->left = tlv_len;
+		} else {
+			sel->left = tlv_len;
+		}
+		if(type_variant == ASN_OSUBV_ANY
+		&& (tag_mode != 1 || sel->cont_level))
+			APPEND(buf_ptr, tlvl);
+		sel->got += tlvl;
+		ADVANCE(tlvl);
+
+		ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%d",
+			(long)sel->got, (long)sel->left,
+			sel->want_nulls, sel->cont_level);
+
+	  } while(tlv_constr);
+		if(sel == NULL) {
+			/* Finished operation, "phase out" */
+			ASN_DEBUG("Phase out");
+			_CH_PHASE(ctx, +3);
+			break;
+		}
+
+		NEXT_PHASE(ctx);
+		/* Fall through */
+	case 2:
+		stck = (struct _stack *)ctx->ptr;
+		sel = stck->cur_ptr;
+		ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d",
+			(long)sel->left, (long)size, (long)sel->got,
+				sel->want_nulls);
+	    {
+		ber_tlv_len_t len;
+
+		assert(sel->left >= 0);
+
+		len = ((ber_tlv_len_t)size < sel->left)
+				? (ber_tlv_len_t)size : sel->left;
+		if(len > 0) {
+			if(type_variant == ASN_OSUBV_BIT
+			&& sel->bits_chopped == 0) {
+				/* Put the unused-bits-octet away */
+				st->bits_unused = *(const uint8_t *)buf_ptr;
+				APPEND(((const char *)buf_ptr+1), (len - 1));
+				sel->bits_chopped = 1;
+			} else {
+				APPEND(buf_ptr, len);
+			}
+			ADVANCE(len);
+			sel->left -= len;
+			sel->got += len;
+		}
+
+		if(sel->left) {
+			ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n",
+				(long)sel->left, (long)size, sel->want_nulls);
+			RETURN(RC_WMORE);
+		}
+
+		PREV_PHASE(ctx);
+		goto phase1;
+	    }
+		break;
+	case 3:
+	phase3:
+		/*
+		 * Primitive form, no stack required.
+		 */
+		assert(ctx->left >= 0);
+
+		if(size < (size_t)ctx->left) {
+			if(!size) RETURN(RC_WMORE);
+			if(type_variant == ASN_OSUBV_BIT && !ctx->context) {
+				st->bits_unused = *(const uint8_t *)buf_ptr;
+				ctx->left--;
+				ADVANCE(1);
+			}
+			APPEND(buf_ptr, size);
+			assert(ctx->context > 0);
+			ctx->left -= size;
+			ADVANCE(size);
+			RETURN(RC_WMORE);
+		} else {
+			if(type_variant == ASN_OSUBV_BIT
+			&& !ctx->context && ctx->left) {
+				st->bits_unused = *(const uint8_t *)buf_ptr;
+				ctx->left--;
+				ADVANCE(1);
+			}
+			APPEND(buf_ptr, ctx->left);
+			ADVANCE(ctx->left);
+			ctx->left = 0;
+
+			NEXT_PHASE(ctx);
+		}
+		break;
+	}
+
+	if(sel) {
+		ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld",
+			sel->prev, sel->want_nulls,
+			(long)sel->left, (long)sel->got, (long)size);
+		if(sel->prev || sel->want_nulls > 1 || sel->left > 0) {
+			RETURN(RC_WMORE);
+		}
+	}
+
+	/*
+	 * BIT STRING-specific processing.
+	 */
+	if(type_variant == ASN_OSUBV_BIT && st->size) {
+		/* Finalize BIT STRING: zero out unused bits. */
+		st->buf[st->size-1] &= 0xff << st->bits_unused;
+	}
+
+	ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
+		(long)consumed_myself, td->name,
+		(type_variant == ASN_OSUBV_STR) ? (char *)st->buf : "<data>",
+		(long)st->size);
+
+
+	RETURN(RC_OK);
+}
+
+/*
+ * Encode OCTET STRING type using DER.
+ */
+asn_enc_rval_t
+OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
+	int tag_mode, ber_tlv_tag_t tag,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_enc_rval_t er;
+	asn_OCTET_STRING_specifics_t *specs = td->specifics
+				? (asn_OCTET_STRING_specifics_t *)td->specifics
+				: &asn_DEF_OCTET_STRING_specs;
+	BIT_STRING_t *st = (BIT_STRING_t *)sptr;
+	enum asn_OS_Subvariant type_variant = specs->subvariant;
+	int fix_last_byte = 0;
+
+	ASN_DEBUG("%s %s as OCTET STRING",
+		cb?"Estimating":"Encoding", td->name);
+
+	/*
+	 * Write tags.
+	 */
+	if(type_variant != ASN_OSUBV_ANY || tag_mode == 1) {
+		er.encoded = der_write_tags(td,
+				(type_variant == ASN_OSUBV_BIT) + st->size,
+			tag_mode, type_variant == ASN_OSUBV_ANY, tag,
+			cb, app_key);
+		if(er.encoded == -1) {
+			er.failed_type = td;
+			er.structure_ptr = sptr;
+			return er;
+		}
+	} else {
+		/* Disallow: [<tag>] IMPLICIT ANY */
+		assert(type_variant != ASN_OSUBV_ANY || tag_mode != -1);
+		er.encoded = 0;
+	}
+
+	if(!cb) {
+		er.encoded += (type_variant == ASN_OSUBV_BIT) + st->size;
+		ASN__ENCODED_OK(er);
+	}
+
+	/*
+	 * Prepare to deal with the last octet of BIT STRING.
+	 */
+	if(type_variant == ASN_OSUBV_BIT) {
+		uint8_t b = st->bits_unused & 0x07;
+		if(b && st->size) fix_last_byte = 1;
+		ASN__CALLBACK(&b, 1);
+		er.encoded++;
+	}
+
+	/* Invoke callback for the main part of the buffer */
+	ASN__CALLBACK(st->buf, st->size - fix_last_byte);
+
+	/* The last octet should be stripped off the unused bits */
+	if(fix_last_byte) {
+		uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused);
+		ASN__CALLBACK(&b, 1);
+	}
+
+	er.encoded += st->size;
+	ASN__ENCODED_OK(er);
+cb_failed:
+	ASN__ENCODE_FAILED;
+}
+
+asn_enc_rval_t
+OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	const char * const h2c = "0123456789ABCDEF";
+	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
+	asn_enc_rval_t er;
+	char scratch[16 * 3 + 4];
+	char *p = scratch;
+	uint8_t *buf;
+	uint8_t *end;
+	size_t i;
+
+	if(!st || (!st->buf && st->size))
+		ASN__ENCODE_FAILED;
+
+	er.encoded = 0;
+
+	/*
+	 * Dump the contents of the buffer in hexadecimal.
+	 */
+	buf = st->buf;
+	end = buf + st->size;
+	if(flags & XER_F_CANONICAL) {
+		char *scend = scratch + (sizeof(scratch) - 2);
+		for(; buf < end; buf++) {
+			if(p >= scend) {
+				ASN__CALLBACK(scratch, p - scratch);
+				er.encoded += p - scratch;
+				p = scratch;
+			}
+			*p++ = h2c[(*buf >> 4) & 0x0F];
+			*p++ = h2c[*buf & 0x0F];
+		}
+
+		ASN__CALLBACK(scratch, p-scratch);	/* Dump the rest */
+		er.encoded += p - scratch;
+	} else {
+		for(i = 0; buf < end; buf++, i++) {
+			if(!(i % 16) && (i || st->size > 16)) {
+				ASN__CALLBACK(scratch, p-scratch);
+				er.encoded += (p-scratch);
+				p = scratch;
+				ASN__TEXT_INDENT(1, ilevel);
+			}
+			*p++ = h2c[(*buf >> 4) & 0x0F];
+			*p++ = h2c[*buf & 0x0F];
+			*p++ = 0x20;
+		}
+		if(p - scratch) {
+			p--;	/* Remove the tail space */
+			ASN__CALLBACK(scratch, p-scratch); /* Dump the rest */
+			er.encoded += p - scratch;
+			if(st->size > 16)
+				ASN__TEXT_INDENT(1, ilevel-1);
+		}
+	}
+
+	ASN__ENCODED_OK(er);
+cb_failed:
+	ASN__ENCODE_FAILED;
+}
+
+static const struct OCTET_STRING__xer_escape_table_s {
+	const char *string;
+	int size;
+} OCTET_STRING__xer_escape_table[] = {
+#define	OSXET(s)	{ s, sizeof(s) - 1 }
+	OSXET("\074\156\165\154\057\076"),	/* <nul/> */
+	OSXET("\074\163\157\150\057\076"),	/* <soh/> */
+	OSXET("\074\163\164\170\057\076"),	/* <stx/> */
+	OSXET("\074\145\164\170\057\076"),	/* <etx/> */
+	OSXET("\074\145\157\164\057\076"),	/* <eot/> */
+	OSXET("\074\145\156\161\057\076"),	/* <enq/> */
+	OSXET("\074\141\143\153\057\076"),	/* <ack/> */
+	OSXET("\074\142\145\154\057\076"),	/* <bel/> */
+	OSXET("\074\142\163\057\076"),		/* <bs/> */
+	OSXET("\011"),				/* \t */
+	OSXET("\012"),				/* \n */
+	OSXET("\074\166\164\057\076"),		/* <vt/> */
+	OSXET("\074\146\146\057\076"),		/* <ff/> */
+	OSXET("\015"),				/* \r */
+	OSXET("\074\163\157\057\076"),		/* <so/> */
+	OSXET("\074\163\151\057\076"),		/* <si/> */
+	OSXET("\074\144\154\145\057\076"),	/* <dle/> */
+	OSXET("\074\144\143\061\057\076"),	/* <de1/> */
+	OSXET("\074\144\143\062\057\076"),	/* <de2/> */
+	OSXET("\074\144\143\063\057\076"),	/* <de3/> */
+	OSXET("\074\144\143\064\057\076"),	/* <de4/> */
+	OSXET("\074\156\141\153\057\076"),	/* <nak/> */
+	OSXET("\074\163\171\156\057\076"),	/* <syn/> */
+	OSXET("\074\145\164\142\057\076"),	/* <etb/> */
+	OSXET("\074\143\141\156\057\076"),	/* <can/> */
+	OSXET("\074\145\155\057\076"),		/* <em/> */
+	OSXET("\074\163\165\142\057\076"),	/* <sub/> */
+	OSXET("\074\145\163\143\057\076"),	/* <esc/> */
+	OSXET("\074\151\163\064\057\076"),	/* <is4/> */
+	OSXET("\074\151\163\063\057\076"),	/* <is3/> */
+	OSXET("\074\151\163\062\057\076"),	/* <is2/> */
+	OSXET("\074\151\163\061\057\076"),	/* <is1/> */
+	{ 0, 0 },	/* " " */
+	{ 0, 0 },	/* ! */
+	{ 0, 0 },	/* \" */
+	{ 0, 0 },	/* # */
+	{ 0, 0 },	/* $ */
+	{ 0, 0 },	/* % */
+	OSXET("\046\141\155\160\073"),	/* &amp; */
+	{ 0, 0 },	/* ' */
+	{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* ()*+,-./ */
+	{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* 01234567 */
+	{0,0},{0,0},{0,0},{0,0},			 /* 89:; */
+	OSXET("\046\154\164\073"),	/* &lt; */
+	{ 0, 0 },	/* = */
+	OSXET("\046\147\164\073"),	/* &gt; */
+};
+
+static int
+OS__check_escaped_control_char(const void *buf, int size) {
+	size_t i;
+	/*
+	 * Inefficient algorithm which translates the escape sequences
+	 * defined above into characters. Returns -1 if not found.
+	 * TODO: replace by a faster algorithm (bsearch(), hash or
+	 * nested table lookups).
+	 */
+	for(i = 0; i < 32 /* Don't spend time on the bottom half */; i++) {
+		const struct OCTET_STRING__xer_escape_table_s *el;
+		el = &OCTET_STRING__xer_escape_table[i];
+		if(el->size == size && memcmp(buf, el->string, size) == 0)
+			return i;
+	}
+	return -1;
+}
+
+static int
+OCTET_STRING__handle_control_chars(void *struct_ptr, const void *chunk_buf, size_t chunk_size) {
+	/*
+	 * This might be one of the escape sequences
+	 * for control characters. Check it out.
+	 * #11.15.5
+	 */
+	int control_char = OS__check_escaped_control_char(chunk_buf,chunk_size);
+	if(control_char >= 0) {
+		OCTET_STRING_t *st = (OCTET_STRING_t *)struct_ptr;
+		void *p = REALLOC(st->buf, st->size + 2);
+		if(p) {
+			st->buf = (uint8_t *)p;
+			st->buf[st->size++] = control_char;
+			st->buf[st->size] = '\0';	/* nul-termination */
+			return 0;
+		}
+	}
+	
+	return -1;	/* No, it's not */
+}
+
+asn_enc_rval_t
+OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
+	asn_enc_rval_t er;
+	uint8_t *buf, *end;
+	uint8_t *ss;	/* Sequence start */
+	ssize_t encoded_len = 0;
+
+	(void)ilevel;	/* Unused argument */
+	(void)flags;	/* Unused argument */
+
+	if(!st || (!st->buf && st->size))
+		ASN__ENCODE_FAILED;
+
+	buf = st->buf;
+	end = buf + st->size;
+	for(ss = buf; buf < end; buf++) {
+		unsigned int ch = *buf;
+		int s_len;	/* Special encoding sequence length */
+
+		/*
+		 * Escape certain characters: X.680/11.15
+		 */
+		if(ch < sizeof(OCTET_STRING__xer_escape_table)
+			/sizeof(OCTET_STRING__xer_escape_table[0])
+		&& (s_len = OCTET_STRING__xer_escape_table[ch].size)) {
+			if(((buf - ss) && cb(ss, buf - ss, app_key) < 0)
+			|| cb(OCTET_STRING__xer_escape_table[ch].string, s_len,
+					app_key) < 0)
+				ASN__ENCODE_FAILED;
+			encoded_len += (buf - ss) + s_len;
+			ss = buf + 1;
+		}
+	}
+
+	encoded_len += (buf - ss);
+	if((buf - ss) && cb(ss, buf - ss, app_key) < 0)
+		ASN__ENCODE_FAILED;
+
+	er.encoded = encoded_len;
+	ASN__ENCODED_OK(er);
+}
+
+/*
+ * Convert from hexadecimal format (cstring): "AB CD EF"
+ */
+static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
+	OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
+	const char *chunk_stop = (const char *)chunk_buf;
+	const char *p = chunk_stop;
+	const char *pend = p + chunk_size;
+	unsigned int clv = 0;
+	int half = 0;	/* Half bit */
+	uint8_t *buf;
+
+	/* Reallocate buffer according to high cap estimation */
+	ssize_t _ns = st->size + (chunk_size + 1) / 2;
+	void *nptr = REALLOC(st->buf, _ns + 1);
+	if(!nptr) return -1;
+	st->buf = (uint8_t *)nptr;
+	buf = st->buf + st->size;
+
+	/*
+	 * If something like " a b c " appears here, the " a b":3 will be
+	 * converted, and the rest skipped. That is, unless buf_size is greater
+	 * than chunk_size, then it'll be equivalent to "ABC0".
+	 */
+	for(; p < pend; p++) {
+		int ch = *(const unsigned char *)p;
+		switch(ch) {
+		case 0x09: case 0x0a: case 0x0c: case 0x0d:
+		case 0x20:
+			/* Ignore whitespace */
+			continue;
+		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
+		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
+			clv = (clv << 4) + (ch - 0x30);
+			break;
+		case 0x41: case 0x42: case 0x43:	/* ABC */
+		case 0x44: case 0x45: case 0x46:	/* DEF */
+			clv = (clv << 4) + (ch - 0x41 + 10);
+			break;
+		case 0x61: case 0x62: case 0x63:	/* abc */
+		case 0x64: case 0x65: case 0x66:	/* def */
+			clv = (clv << 4) + (ch - 0x61 + 10);
+			break;
+		default:
+			*buf = 0;	/* JIC */
+			return -1;
+		}
+		if(half++) {
+			half = 0;
+			*buf++ = clv;
+			chunk_stop = p + 1;
+		}
+	}
+
+	/*
+	 * Check partial decoding.
+	 */
+	if(half) {
+		if(have_more) {
+			/*
+			 * Partial specification is fine,
+			 * because no more more PXER_TEXT data is available.
+			 */
+			*buf++ = clv << 4;
+			chunk_stop = p;
+		}
+	} else {
+		chunk_stop = p;
+	}
+
+	st->size = buf - st->buf;	/* Adjust the buffer size */
+	assert(st->size <= _ns);
+	st->buf[st->size] = 0;		/* Courtesy termination */
+
+	return (chunk_stop - (const char *)chunk_buf);	/* Converted size */
+}
+
+/*
+ * Convert from binary format: "00101011101"
+ */
+static ssize_t OCTET_STRING__convert_binary(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
+	BIT_STRING_t *st = (BIT_STRING_t *)sptr;
+	const char *p = (const char *)chunk_buf;
+	const char *pend = p + chunk_size;
+	int bits_unused = st->bits_unused & 0x7;
+	uint8_t *buf;
+
+	/* Reallocate buffer according to high cap estimation */
+	ssize_t _ns = st->size + (chunk_size + 7) / 8;
+	void *nptr = REALLOC(st->buf, _ns + 1);
+	if(!nptr) return -1;
+	st->buf = (uint8_t *)nptr;
+	buf = st->buf + st->size;
+
+	(void)have_more;
+
+	if(bits_unused == 0)
+		bits_unused = 8;
+	else if(st->size)
+		buf--;
+
+	/*
+	 * Convert series of 0 and 1 into the octet string.
+	 */
+	for(; p < pend; p++) {
+		int ch = *(const unsigned char *)p;
+		switch(ch) {
+		case 0x09: case 0x0a: case 0x0c: case 0x0d:
+		case 0x20:
+			/* Ignore whitespace */
+			break;
+		case 0x30:
+		case 0x31:
+			if(bits_unused-- <= 0) {
+				*++buf = 0;	/* Clean the cell */
+				bits_unused = 7;
+			}
+			*buf |= (ch&1) << bits_unused;
+			break;
+		default:
+			st->bits_unused = bits_unused;
+			return -1;
+		}
+	}
+
+	if(bits_unused == 8) {
+		st->size = buf - st->buf;
+		st->bits_unused = 0;
+	} else {
+		st->size = buf - st->buf + 1;
+		st->bits_unused = bits_unused;
+	}
+
+	assert(st->size <= _ns);
+	st->buf[st->size] = 0;		/* Courtesy termination */
+
+	return chunk_size;	/* Converted in full */
+}
+
+/*
+ * Something like strtod(), but with stricter rules.
+ */
+static int
+OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) {
+	int32_t val = 0;
+	const char *p;
+
+	for(p = buf; p < end; p++) {
+		int ch = *p;
+
+		/* Strange huge value */
+		if((val * base + base) < 0)
+			return -1;
+
+		switch(ch) {
+		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
+		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
+			val = val * base + (ch - 0x30);
+			break;
+		case 0x41: case 0x42: case 0x43:	/* ABC */
+		case 0x44: case 0x45: case 0x46:	/* DEF */
+			val = val * base + (ch - 0x41 + 10);
+			break;
+		case 0x61: case 0x62: case 0x63:	/* abc */
+		case 0x64: case 0x65: case 0x66:	/* def */
+			val = val * base + (ch - 0x61 + 10);
+			break;
+		case 0x3b:	/* ';' */
+			*ret_value = val;
+			return (p - buf) + 1;
+		default:
+			return -1;	/* Character set error */
+		}
+	}
+
+	*ret_value = -1;
+	return (p - buf);
+}
+
+/*
+ * Convert from the plain UTF-8 format, expanding entity references: "2 &lt; 3"
+ */
+static ssize_t OCTET_STRING__convert_entrefs(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
+	OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
+	const char *p = (const char *)chunk_buf;
+	const char *pend = p + chunk_size;
+	uint8_t *buf;
+
+	/* Reallocate buffer */
+	ssize_t _ns = st->size + chunk_size;
+	void *nptr = REALLOC(st->buf, _ns + 1);
+	if(!nptr) return -1;
+	st->buf = (uint8_t *)nptr;
+	buf = st->buf + st->size;
+
+	/*
+	 * Convert series of 0 and 1 into the octet string.
+	 */
+	for(; p < pend; p++) {
+		int ch = *(const unsigned char *)p;
+		int len;	/* Length of the rest of the chunk */
+
+		if(ch != 0x26 /* '&' */) {
+			*buf++ = ch;
+			continue;	/* That was easy... */
+		}
+
+		/*
+		 * Process entity reference.
+		 */
+		len = chunk_size - (p - (const char *)chunk_buf);
+		if(len == 1 /* "&" */) goto want_more;
+		if(p[1] == 0x23 /* '#' */) {
+			const char *pval;	/* Pointer to start of digits */
+			int32_t val = 0;	/* Entity reference value */
+			int base;
+
+			if(len == 2 /* "&#" */) goto want_more;
+			if(p[2] == 0x78 /* 'x' */)
+				pval = p + 3, base = 16;
+			else
+				pval = p + 2, base = 10;
+			len = OS__strtoent(base, pval, p + len, &val);
+			if(len == -1) {
+				/* Invalid charset. Just copy verbatim. */
+				*buf++ = ch;
+				continue;
+			}
+			if(!len || pval[len-1] != 0x3b) goto want_more;
+			assert(val > 0);
+			p += (pval - p) + len - 1; /* Advance past entref */
+
+			if(val < 0x80) {
+				*buf++ = (char)val;
+			} else if(val < 0x800) {
+				*buf++ = 0xc0 | ((val >> 6));
+				*buf++ = 0x80 | ((val & 0x3f));
+			} else if(val < 0x10000) {
+				*buf++ = 0xe0 | ((val >> 12));
+				*buf++ = 0x80 | ((val >> 6) & 0x3f);
+				*buf++ = 0x80 | ((val & 0x3f));
+			} else if(val < 0x200000) {
+				*buf++ = 0xf0 | ((val >> 18));
+				*buf++ = 0x80 | ((val >> 12) & 0x3f);
+				*buf++ = 0x80 | ((val >> 6) & 0x3f);
+				*buf++ = 0x80 | ((val & 0x3f));
+			} else if(val < 0x4000000) {
+				*buf++ = 0xf8 | ((val >> 24));
+				*buf++ = 0x80 | ((val >> 18) & 0x3f);
+				*buf++ = 0x80 | ((val >> 12) & 0x3f);
+				*buf++ = 0x80 | ((val >> 6) & 0x3f);
+				*buf++ = 0x80 | ((val & 0x3f));
+			} else {
+				*buf++ = 0xfc | ((val >> 30) & 0x1);
+				*buf++ = 0x80 | ((val >> 24) & 0x3f);
+				*buf++ = 0x80 | ((val >> 18) & 0x3f);
+				*buf++ = 0x80 | ((val >> 12) & 0x3f);
+				*buf++ = 0x80 | ((val >> 6) & 0x3f);
+				*buf++ = 0x80 | ((val & 0x3f));
+			}
+		} else {
+			/*
+			 * Ugly, limited parsing of &amp; &gt; &lt;
+			 */
+			char *sc = (char *)memchr(p, 0x3b, len > 5 ? 5 : len);
+			if(!sc) goto want_more;
+			if((sc - p) == 4
+				&& p[1] == 0x61	/* 'a' */
+				&& p[2] == 0x6d	/* 'm' */
+				&& p[3] == 0x70	/* 'p' */) {
+				*buf++ = 0x26;
+				p = sc;
+				continue;
+			}
+			if((sc - p) == 3) {
+				if(p[1] == 0x6c) {
+					*buf = 0x3c;	/* '<' */
+				} else if(p[1] == 0x67) {
+					*buf = 0x3e;	/* '>' */
+				} else {
+					/* Unsupported entity reference */
+					*buf++ = ch;
+					continue;
+				}
+				if(p[2] != 0x74) {
+					/* Unsupported entity reference */
+					*buf++ = ch;
+					continue;
+				}
+				buf++;
+				p = sc;
+				continue;
+			}
+			/* Unsupported entity reference */
+			*buf++ = ch;
+		}
+
+		continue;
+	want_more:
+		if(have_more) {
+			/*
+			 * We know that no more data (of the same type)
+			 * is coming. Copy the rest verbatim.
+			 */
+			*buf++ = ch;
+			continue;
+		}
+		chunk_size = (p - (const char *)chunk_buf);
+		/* Processing stalled: need more data */
+		break;
+	}
+
+	st->size = buf - st->buf;
+	assert(st->size <= _ns);
+	st->buf[st->size] = 0;		/* Courtesy termination */
+
+	return chunk_size;	/* Converted in full */
+}
+
+/*
+ * Decode OCTET STRING from the XML element's body.
+ */
+static asn_dec_rval_t
+OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td, void **sptr,
+	const char *opt_mname, const void *buf_ptr, size_t size,
+	int (*opt_unexpected_tag_decoder)
+		(void *struct_ptr, const void *chunk_buf, size_t chunk_size),
+	ssize_t (*body_receiver)
+		(void *struct_ptr, const void *chunk_buf, size_t chunk_size,
+			int have_more)
+) {
+	OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
+	asn_OCTET_STRING_specifics_t *specs = td->specifics
+				? (asn_OCTET_STRING_specifics_t *)td->specifics
+				: &asn_DEF_OCTET_STRING_specs;
+	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
+	asn_struct_ctx_t *ctx;		/* Per-structure parser context */
+	asn_dec_rval_t rval;		/* Return value from the decoder */
+	int st_allocated;
+
+	/*
+	 * Create the string if does not exist.
+	 */
+	if(!st) {
+		st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
+		*sptr = (void *)st;
+		if(!st) goto sta_failed;
+		st_allocated = 1;
+	} else {
+		st_allocated = 0;
+	}
+	if(!st->buf) {
+		/* This is separate from above section */
+		st->buf = (uint8_t *)CALLOC(1, 1);
+		if(!st->buf) {
+			if(st_allocated) {
+				*sptr = 0;
+				goto stb_failed;
+			} else {
+				goto sta_failed;
+			}
+		}
+	}
+
+	/* Restore parsing context */
+	ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset);
+
+	return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag,
+		buf_ptr, size, opt_unexpected_tag_decoder, body_receiver);
+
+stb_failed:
+	FREEMEM(st);
+sta_failed:
+	rval.code = RC_FAIL;
+	rval.consumed = 0;
+	return rval;
+}
+
+/*
+ * Decode OCTET STRING from the hexadecimal data.
+ */
+asn_dec_rval_t
+OCTET_STRING_decode_xer_hex(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td, void **sptr,
+		const char *opt_mname, const void *buf_ptr, size_t size) {
+	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
+		buf_ptr, size, 0, OCTET_STRING__convert_hexadecimal);
+}
+
+/*
+ * Decode OCTET STRING from the binary (0/1) data.
+ */
+asn_dec_rval_t
+OCTET_STRING_decode_xer_binary(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td, void **sptr,
+		const char *opt_mname, const void *buf_ptr, size_t size) {
+	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
+		buf_ptr, size, 0, OCTET_STRING__convert_binary);
+}
+
+/*
+ * Decode OCTET STRING from the string (ASCII/UTF-8) data.
+ */
+asn_dec_rval_t
+OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td, void **sptr,
+		const char *opt_mname, const void *buf_ptr, size_t size) {
+	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
+		buf_ptr, size,
+		OCTET_STRING__handle_control_chars,
+		OCTET_STRING__convert_entrefs);
+}
+
+static int
+OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
+		size_t units, unsigned int bpc, unsigned int unit_bits,
+		long lb, long ub, asn_per_constraints_t *pc) {
+	uint8_t *end = buf + units * bpc;
+
+	ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d",
+		(int)units, lb, ub, unit_bits);
+
+	/* X.691: 27.5.4 */
+	if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
+		/* Decode without translation */
+		lb = 0;
+	} else if(pc && pc->code2value) {
+		if(unit_bits > 16)
+			return 1;	/* FATAL: can't have constrained
+					 * UniversalString with more than
+					 * 16 million code points */
+		for(; buf < end; buf += bpc) {
+			int value;
+			int code = per_get_few_bits(po, unit_bits);
+			if(code < 0) return -1;	/* WMORE */
+			value = pc->code2value(code);
+			if(value < 0) {
+				ASN_DEBUG("Code %d (0x%02x) is"
+					" not in map (%ld..%ld)",
+					code, code, lb, ub);
+				return 1;	/* FATAL */
+			}
+			switch(bpc) {
+			case 1: *buf = value; break;
+			case 2: buf[0] = value >> 8; buf[1] = value; break;
+			case 4: buf[0] = value >> 24; buf[1] = value >> 16;
+				buf[2] = value >> 8; buf[3] = value; break;
+			}
+		}
+		return 0;
+	}
+
+	/* Shortcut the no-op copying to the aligned structure */
+	if(lb == 0 && (unit_bits == 8 * bpc)) {
+		return per_get_many_bits(po, buf, 0, unit_bits * units);
+	}
+
+	for(; buf < end; buf += bpc) {
+		int code = per_get_few_bits(po, unit_bits);
+		int ch = code + lb;
+		if(code < 0) return -1;	/* WMORE */
+		if(ch > ub) {
+			ASN_DEBUG("Code %d is out of range (%ld..%ld)",
+				ch, lb, ub);
+			return 1;	/* FATAL */
+		}
+		switch(bpc) {
+		case 1: *buf = ch; break;
+		case 2: buf[0] = ch >> 8; buf[1] = ch; break;
+		case 4: buf[0] = ch >> 24; buf[1] = ch >> 16;
+			buf[2] = ch >> 8; buf[3] = ch; break;
+		}
+	}
+
+	return 0;
+}
+
+static int
+OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
+		size_t units, unsigned int bpc, unsigned int unit_bits,
+		long lb, long ub, asn_per_constraints_t *pc) {
+	const uint8_t *end = buf + units * bpc;
+
+	ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)",
+		(int)units, lb, ub, unit_bits, bpc);
+
+	/* X.691: 27.5.4 */
+	if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
+		/* Encode as is */
+		lb = 0;
+	} else if(pc && pc->value2code) {
+		for(; buf < end; buf += bpc) {
+			int code;
+			uint32_t value;
+			switch(bpc) {
+			case 1: value = *(const uint8_t *)buf; break;
+			case 2: value = (buf[0] << 8) | buf[1]; break;
+			case 4: value = (buf[0] << 24) | (buf[1] << 16)
+					| (buf[2] << 8) | buf[3]; break;
+			default: return -1;
+			}
+			code = pc->value2code(value);
+			if(code < 0) {
+				ASN_DEBUG("Character %d (0x%02x) is"
+					" not in map (%ld..%ld)",
+					*buf, *buf, lb, ub);
+				return -1;
+			}
+			if(per_put_few_bits(po, code, unit_bits))
+				return -1;
+		}
+	}
+
+	/* Shortcut the no-op copying to the aligned structure */
+	if(lb == 0 && (unit_bits == 8 * bpc)) {
+		return per_put_many_bits(po, buf, unit_bits * units);
+	}
+
+	for(ub -= lb; buf < end; buf += bpc) {
+		int ch;
+		uint32_t value;
+		switch(bpc) {
+		case 1: value = *(const uint8_t *)buf; break;
+		case 2: value = (buf[0] << 8) | buf[1]; break;
+		case 4: value = (buf[0] << 24) | (buf[1] << 16)
+				| (buf[2] << 8) | buf[3]; break;
+		default: return -1;
+		}
+		ch = value - lb;
+		if(ch < 0 || ch > ub) {
+			ASN_DEBUG("Character %d (0x%02x)"
+			" is out of range (%ld..%ld)",
+				*buf, *buf, lb, ub + lb);
+			return -1;
+		}
+		if(per_put_few_bits(po, ch, unit_bits))
+			return -1;
+	}
+
+	return 0;
+}
+
+asn_dec_rval_t
+OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+	void **sptr, asn_per_data_t *pd) {
+
+	asn_OCTET_STRING_specifics_t *specs = td->specifics
+		? (asn_OCTET_STRING_specifics_t *)td->specifics
+		: &asn_DEF_OCTET_STRING_specs;
+	asn_per_constraints_t *pc = constraints ? constraints
+				: td->per_constraints;
+	asn_per_constraint_t *cval;
+	asn_per_constraint_t *csiz;
+	asn_dec_rval_t rval = { RC_OK, 0 };
+	BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
+	ssize_t consumed_myself = 0;
+	int repeat;
+	enum {
+		OS__BPC_BIT	= 0,
+		OS__BPC_CHAR	= 1,
+		OS__BPC_U16	= 2,
+		OS__BPC_U32	= 4
+	} bpc;	/* Bytes per character */
+	unsigned int unit_bits;
+	unsigned int canonical_unit_bits;
+
+	(void)opt_codec_ctx;
+
+	if(pc) {
+		cval = &pc->value;
+		csiz = &pc->size;
+	} else {
+		cval = &asn_DEF_OCTET_STRING_constraints.value;
+		csiz = &asn_DEF_OCTET_STRING_constraints.size;
+	}
+
+	switch(specs->subvariant) {
+	default:
+	case ASN_OSUBV_ANY:
+		ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
+		RETURN(RC_FAIL);
+	case ASN_OSUBV_BIT:
+		canonical_unit_bits = unit_bits = 1;
+		bpc = OS__BPC_BIT;
+		break;
+	case ASN_OSUBV_STR:
+		canonical_unit_bits = unit_bits = 8;
+		if(cval->flags & APC_CONSTRAINED)
+			unit_bits = cval->range_bits;
+		bpc = OS__BPC_CHAR;
+		break;
+	case ASN_OSUBV_U16:
+		canonical_unit_bits = unit_bits = 16;
+		if(cval->flags & APC_CONSTRAINED)
+			unit_bits = cval->range_bits;
+		bpc = OS__BPC_U16;
+		break;
+	case ASN_OSUBV_U32:
+		canonical_unit_bits = unit_bits = 32;
+		if(cval->flags & APC_CONSTRAINED)
+			unit_bits = cval->range_bits;
+		bpc = OS__BPC_U32;
+		break;
+	}
+
+	/*
+	 * Allocate the string.
+	 */
+	if(!st) {
+		st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
+		if(!st) RETURN(RC_FAIL);
+	}
+
+	ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
+		csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
+		csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
+
+	if(csiz->flags & APC_EXTENSIBLE) {
+		int inext = per_get_few_bits(pd, 1);
+		if(inext < 0) RETURN(RC_WMORE);
+		if(inext) {
+			csiz = &asn_DEF_OCTET_STRING_constraints.size;
+			cval = &asn_DEF_OCTET_STRING_constraints.value;
+			unit_bits = canonical_unit_bits;
+		}
+	}
+
+	if(csiz->effective_bits >= 0) {
+		FREEMEM(st->buf);
+		if(bpc) {
+			st->size = csiz->upper_bound * bpc;
+		} else {
+			st->size = (csiz->upper_bound + 7) >> 3;
+		}
+		st->buf = (uint8_t *)MALLOC(st->size + 1);
+		if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
+	}
+
+	/* X.691, #16.5: zero-length encoding */
+	/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
+	/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
+	if(csiz->effective_bits == 0) {
+		int ret;
+		if(bpc) {
+			ASN_DEBUG("Encoding OCTET STRING size %ld",
+				csiz->upper_bound);
+			ret = OCTET_STRING_per_get_characters(pd, st->buf,
+				csiz->upper_bound, bpc, unit_bits,
+				cval->lower_bound, cval->upper_bound, pc);
+			if(ret > 0) RETURN(RC_FAIL);
+		} else {
+			ASN_DEBUG("Encoding BIT STRING size %ld",
+				csiz->upper_bound);
+			ret = per_get_many_bits(pd, st->buf, 0,
+					    unit_bits * csiz->upper_bound);
+		}
+		if(ret < 0) RETURN(RC_WMORE);
+		consumed_myself += unit_bits * csiz->upper_bound;
+		st->buf[st->size] = 0;
+		if(bpc == 0) {
+			int ubs = (csiz->upper_bound & 0x7);
+			st->bits_unused = ubs ? 8 - ubs : 0;
+		}
+		RETURN(RC_OK);
+	}
+
+	st->size = 0;
+	do {
+		ssize_t raw_len;
+		ssize_t len_bytes;
+		ssize_t len_bits;
+		void *p;
+		int ret;
+
+		/* Get the PER length */
+		raw_len = uper_get_length(pd, csiz->effective_bits, &repeat);
+		if(raw_len < 0) RETURN(RC_WMORE);
+		raw_len += csiz->lower_bound;
+
+		ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
+			(long)csiz->effective_bits, (long)raw_len,
+			repeat ? "repeat" : "once", td->name);
+		if(bpc) {
+			len_bytes = raw_len * bpc;
+			len_bits = len_bytes * unit_bits;
+		} else {
+			len_bits = raw_len;
+			len_bytes = (len_bits + 7) >> 3;
+			if(len_bits & 0x7)
+				st->bits_unused = 8 - (len_bits & 0x7);
+			/* len_bits be multiple of 16K if repeat is set */
+		}
+		p = REALLOC(st->buf, st->size + len_bytes + 1);
+		if(!p) RETURN(RC_FAIL);
+		st->buf = (uint8_t *)p;
+
+		if(bpc) {
+			ret = OCTET_STRING_per_get_characters(pd,
+				&st->buf[st->size], raw_len, bpc, unit_bits,
+				cval->lower_bound, cval->upper_bound, pc);
+			if(ret > 0) RETURN(RC_FAIL);
+		} else {
+			ret = per_get_many_bits(pd, &st->buf[st->size],
+				0, len_bits);
+		}
+		if(ret < 0) RETURN(RC_WMORE);
+		st->size += len_bytes;
+	} while(repeat);
+	st->buf[st->size] = 0;	/* nul-terminate */
+
+	return rval;
+}
+
+asn_enc_rval_t
+OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
+        asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+
+	asn_OCTET_STRING_specifics_t *specs = td->specifics
+		? (asn_OCTET_STRING_specifics_t *)td->specifics
+		: &asn_DEF_OCTET_STRING_specs;
+	asn_per_constraints_t *pc = constraints ? constraints
+				: td->per_constraints;
+	asn_per_constraint_t *cval;
+	asn_per_constraint_t *csiz;
+	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
+	asn_enc_rval_t er = { 0, 0, 0 };
+	int inext = 0;		/* Lies not within extension root */
+	unsigned int unit_bits;
+	unsigned int canonical_unit_bits;
+	unsigned int sizeinunits;
+	const uint8_t *buf;
+	int ret;
+	enum {
+		OS__BPC_BIT	= 0,
+		OS__BPC_CHAR	= 1,
+		OS__BPC_U16	= 2,
+		OS__BPC_U32	= 4
+	} bpc;	/* Bytes per character */
+	int ct_extensible;
+
+	if(!st || (!st->buf && st->size))
+		ASN__ENCODE_FAILED;
+
+	if(pc) {
+		cval = &pc->value;
+		csiz = &pc->size;
+	} else {
+		cval = &asn_DEF_OCTET_STRING_constraints.value;
+		csiz = &asn_DEF_OCTET_STRING_constraints.size;
+	}
+	ct_extensible = csiz->flags & APC_EXTENSIBLE;
+
+	switch(specs->subvariant) {
+	default:
+	case ASN_OSUBV_ANY:
+		ASN__ENCODE_FAILED;
+	case ASN_OSUBV_BIT:
+		canonical_unit_bits = unit_bits = 1;
+		bpc = OS__BPC_BIT;
+		sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
+		ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
+				sizeinunits, st->bits_unused);
+		break;
+	case ASN_OSUBV_STR:
+		canonical_unit_bits = unit_bits = 8;
+		if(cval->flags & APC_CONSTRAINED)
+			unit_bits = cval->range_bits;
+		bpc = OS__BPC_CHAR;
+		sizeinunits = st->size;
+		break;
+	case ASN_OSUBV_U16:
+		canonical_unit_bits = unit_bits = 16;
+		if(cval->flags & APC_CONSTRAINED)
+			unit_bits = cval->range_bits;
+		bpc = OS__BPC_U16;
+		sizeinunits = st->size / 2;
+		break;
+	case ASN_OSUBV_U32:
+		canonical_unit_bits = unit_bits = 32;
+		if(cval->flags & APC_CONSTRAINED)
+			unit_bits = cval->range_bits;
+		bpc = OS__BPC_U32;
+		sizeinunits = st->size / 4;
+		break;
+	}
+
+	ASN_DEBUG("Encoding %s into %d units of %d bits"
+		" (%ld..%ld, effective %d)%s",
+		td->name, sizeinunits, unit_bits,
+		csiz->lower_bound, csiz->upper_bound,
+		csiz->effective_bits, ct_extensible ? " EXT" : "");
+
+	/* Figure out whether size lies within PER visible constraint */
+
+	if(csiz->effective_bits >= 0) {
+		if((int)sizeinunits < csiz->lower_bound
+		|| (int)sizeinunits > csiz->upper_bound) {
+			if(ct_extensible) {
+				cval = &asn_DEF_OCTET_STRING_constraints.value;
+				csiz = &asn_DEF_OCTET_STRING_constraints.size;
+				unit_bits = canonical_unit_bits;
+				inext = 1;
+			} else
+				ASN__ENCODE_FAILED;
+		}
+	} else {
+		inext = 0;
+	}
+
+	if(ct_extensible) {
+		/* Declare whether length is [not] within extension root */
+		if(per_put_few_bits(po, inext, 1))
+			ASN__ENCODE_FAILED;
+	}
+
+	/* X.691, #16.5: zero-length encoding */
+	/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
+	/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
+	if(csiz->effective_bits >= 0) {
+		ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
+				st->size, sizeinunits - csiz->lower_bound,
+				csiz->effective_bits);
+		ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
+				csiz->effective_bits);
+		if(ret) ASN__ENCODE_FAILED;
+		if(bpc) {
+			ret = OCTET_STRING_per_put_characters(po, st->buf,
+				sizeinunits, bpc, unit_bits,
+				cval->lower_bound, cval->upper_bound, pc);
+		} else {
+			ret = per_put_many_bits(po, st->buf,
+				sizeinunits * unit_bits);
+		}
+		if(ret) ASN__ENCODE_FAILED;
+		ASN__ENCODED_OK(er);
+	}
+
+	ASN_DEBUG("Encoding %d bytes", st->size);
+
+	if(sizeinunits == 0) {
+		if(uper_put_length(po, 0))
+			ASN__ENCODE_FAILED;
+		ASN__ENCODED_OK(er);
+	}
+
+	buf = st->buf;
+	while(sizeinunits) {
+		ssize_t maySave = uper_put_length(po, sizeinunits);
+		if(maySave < 0) ASN__ENCODE_FAILED;
+
+		ASN_DEBUG("Encoding %ld of %ld",
+			(long)maySave, (long)sizeinunits);
+
+		if(bpc) {
+			ret = OCTET_STRING_per_put_characters(po, buf,
+				maySave, bpc, unit_bits,
+				cval->lower_bound, cval->upper_bound, pc);
+		} else {
+			ret = per_put_many_bits(po, buf, maySave * unit_bits);
+		}
+		if(ret) ASN__ENCODE_FAILED;
+
+		if(bpc)
+			buf += maySave * bpc;
+		else
+			buf += maySave >> 3;
+		sizeinunits -= maySave;
+		assert(!(maySave & 0x07) || !sizeinunits);
+	}
+
+	ASN__ENCODED_OK(er);
+}
+
+int
+OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	const char * const h2c = "0123456789ABCDEF";
+	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
+	char scratch[16 * 3 + 4];
+	char *p = scratch;
+	uint8_t *buf;
+	uint8_t *end;
+	size_t i;
+
+	(void)td;	/* Unused argument */
+
+	if(!st || (!st->buf && st->size))
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+
+	/*
+	 * Dump the contents of the buffer in hexadecimal.
+	 */
+	buf = st->buf;
+	end = buf + st->size;
+	for(i = 0; buf < end; buf++, i++) {
+		if(!(i % 16) && (i || st->size > 16)) {
+			if(cb(scratch, p - scratch, app_key) < 0)
+				return -1;
+			_i_INDENT(1);
+			p = scratch;
+		}
+		*p++ = h2c[(*buf >> 4) & 0x0F];
+		*p++ = h2c[*buf & 0x0F];
+		*p++ = 0x20;
+	}
+
+	if(p > scratch) {
+		p--;	/* Remove the tail space */
+		if(cb(scratch, p - scratch, app_key) < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+int
+OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr,
+		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
+	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
+
+	(void)td;	/* Unused argument */
+	(void)ilevel;	/* Unused argument */
+
+	if(st && (st->buf || !st->size)) {
+		return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
+	} else {
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+	}
+}
+
+void
+OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
+	OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
+	asn_OCTET_STRING_specifics_t *specs;
+	asn_struct_ctx_t *ctx;
+	struct _stack *stck;
+
+	if(!td || !st)
+		return;
+
+	specs = td->specifics
+		    ? (asn_OCTET_STRING_specifics_t *)td->specifics
+		    : &asn_DEF_OCTET_STRING_specs;
+	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
+
+	ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
+
+	if(st->buf) {
+		FREEMEM(st->buf);
+		st->buf = 0;
+	}
+
+	/*
+	 * Remove decode-time stack.
+	 */
+	stck = (struct _stack *)ctx->ptr;
+	if(stck) {
+		while(stck->tail) {
+			struct _stack_el *sel = stck->tail;
+			stck->tail = sel->prev;
+			FREEMEM(sel);
+		}
+		FREEMEM(stck);
+	}
+
+	if(!contents_only) {
+		FREEMEM(st);
+	}
+}
+
+/*
+ * Conversion routines.
+ */
+int
+OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
+	void *buf;
+
+	if(st == 0 || (str == 0 && len)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/*
+	 * Clear the OCTET STRING.
+	 */
+	if(str == NULL) {
+		FREEMEM(st->buf);
+		st->buf = 0;
+		st->size = 0;
+		return 0;
+	}
+
+	/* Determine the original string size, if not explicitly given */
+	if(len < 0)
+		len = strlen(str);
+
+	/* Allocate and fill the memory */
+	buf = MALLOC(len + 1);
+	if(buf == NULL)
+		return -1;
+
+	memcpy(buf, str, len);
+	((uint8_t *)buf)[len] = '\0';	/* Couldn't use memcpy(len+1)! */
+	FREEMEM(st->buf);
+	st->buf = (uint8_t *)buf;
+	st->size = len;
+
+	return 0;
+}
+
+OCTET_STRING_t *
+OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str, int len) {
+	asn_OCTET_STRING_specifics_t *specs = td->specifics
+				? (asn_OCTET_STRING_specifics_t *)td->specifics
+				: &asn_DEF_OCTET_STRING_specs;
+	OCTET_STRING_t *st;
+
+	st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
+	if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
+		FREEMEM(st);
+		st = NULL;
+	}
+
+	return st;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/OCTET_STRING.h b/libkmod/pkcs7/asn1c-gen/OCTET_STRING.h
new file mode 100644
index 000000000000..013c7b13f96c
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/OCTET_STRING.h
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_OCTET_STRING_H_
+#define	_OCTET_STRING_H_
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct OCTET_STRING {
+	uint8_t *buf;	/* Buffer with consecutive OCTET_STRING bits */
+	int size;	/* Size of the buffer */
+
+	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer boundaries */
+} OCTET_STRING_t;
+
+extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING;
+
+asn_struct_free_f OCTET_STRING_free;
+asn_struct_print_f OCTET_STRING_print;
+asn_struct_print_f OCTET_STRING_print_utf8;
+ber_type_decoder_f OCTET_STRING_decode_ber;
+der_type_encoder_f OCTET_STRING_encode_der;
+xer_type_decoder_f OCTET_STRING_decode_xer_hex;		/* Hexadecimal */
+xer_type_decoder_f OCTET_STRING_decode_xer_binary;	/* 01010111010 */
+xer_type_decoder_f OCTET_STRING_decode_xer_utf8;	/* ASCII/UTF-8 */
+xer_type_encoder_f OCTET_STRING_encode_xer;
+xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
+per_type_decoder_f OCTET_STRING_decode_uper;
+per_type_encoder_f OCTET_STRING_encode_uper;
+
+/******************************
+ * Handy conversion routines. *
+ ******************************/
+
+/*
+ * This function clears the previous value of the OCTET STRING (if any)
+ * and then allocates a new memory with the specified content (str/size).
+ * If size = -1, the size of the original string will be determined
+ * using strlen(str).
+ * If str equals to NULL, the function will silently clear the
+ * current contents of the OCTET STRING.
+ * Returns 0 if it was possible to perform operation, -1 otherwise.
+ */
+int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int size);
+
+/* Handy conversion from the C string into the OCTET STRING. */
+#define	OCTET_STRING_fromString(s, str)	OCTET_STRING_fromBuf(s, str, -1)
+
+/*
+ * Allocate and fill the new OCTET STRING and return a pointer to the newly
+ * allocated object. NULL is permitted in str: the function will just allocate
+ * empty OCTET STRING.
+ */
+OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td,
+	const char *str, int size);
+
+/****************************
+ * Internally useful stuff. *
+ ****************************/
+
+typedef const struct asn_OCTET_STRING_specifics_s {
+	/*
+	 * Target structure description.
+	 */
+	int struct_size;	/* Size of the structure */
+	int ctx_offset;		/* Offset of the asn_struct_ctx_t member */
+
+	enum asn_OS_Subvariant {
+		ASN_OSUBV_ANY,	/* The open type (ANY) */
+		ASN_OSUBV_BIT,	/* BIT STRING */
+		ASN_OSUBV_STR,	/* String types, not {BMP,Universal}String  */
+		ASN_OSUBV_U16,	/* 16-bit character (BMPString) */
+		ASN_OSUBV_U32	/* 32-bit character (UniversalString) */
+	} subvariant;
+} asn_OCTET_STRING_specifics_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _OCTET_STRING_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c b/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c
new file mode 100644
index 000000000000..d4f6ffafc696
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c
@@ -0,0 +1,69 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "PKCS7ContentInfo.h"
+
+static asn_TYPE_member_t asn_MBR_PKCS7ContentInfo_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct PKCS7ContentInfo, contentType),
+		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
+		0,
+		&asn_DEF_ContentType,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"contentType"
+		},
+	{ ATF_POINTER, 1, offsetof(struct PKCS7ContentInfo, content),
+		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+		+1,	/* EXPLICIT tag at current level */
+		&asn_DEF_SignedData,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"content"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_PKCS7ContentInfo_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_PKCS7ContentInfo_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /* contentType */
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, 0, 0 } /* content */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_PKCS7ContentInfo_specs_1 = {
+	sizeof(struct PKCS7ContentInfo),
+	offsetof(struct PKCS7ContentInfo, _asn_ctx),
+	asn_MAP_PKCS7ContentInfo_tag2el_1,
+	2,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_PKCS7ContentInfo = {
+	"PKCS7ContentInfo",
+	"PKCS7ContentInfo",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_PKCS7ContentInfo_tags_1,
+	sizeof(asn_DEF_PKCS7ContentInfo_tags_1)
+		/sizeof(asn_DEF_PKCS7ContentInfo_tags_1[0]), /* 1 */
+	asn_DEF_PKCS7ContentInfo_tags_1,	/* Same as above */
+	sizeof(asn_DEF_PKCS7ContentInfo_tags_1)
+		/sizeof(asn_DEF_PKCS7ContentInfo_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_PKCS7ContentInfo_1,
+	2,	/* Elements count */
+	&asn_SPC_PKCS7ContentInfo_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h b/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h
new file mode 100644
index 000000000000..e9e84da96a75
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h
@@ -0,0 +1,45 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_PKCS7ContentInfo_H_
+#define	_PKCS7ContentInfo_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include "ContentType.h"
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct SignedData;
+
+/* PKCS7ContentInfo */
+typedef struct PKCS7ContentInfo {
+	ContentType_t	 contentType;
+	struct SignedData	*content	/* OPTIONAL */;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} PKCS7ContentInfo_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_PKCS7ContentInfo;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "SignedData.h"
+
+#endif	/* _PKCS7ContentInfo_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c b/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c
new file mode 100644
index 000000000000..d84ba39bb7b7
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c
@@ -0,0 +1,52 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "RelativeDistinguishedName.h"
+
+static asn_TYPE_member_t asn_MBR_RelativeDistinguishedName_1[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_AttributeValueAssertion,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_RelativeDistinguishedName_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_RelativeDistinguishedName_specs_1 = {
+	sizeof(struct RelativeDistinguishedName),
+	offsetof(struct RelativeDistinguishedName, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_RelativeDistinguishedName = {
+	"RelativeDistinguishedName",
+	"RelativeDistinguishedName",
+	SET_OF_free,
+	SET_OF_print,
+	SET_OF_constraint,
+	SET_OF_decode_ber,
+	SET_OF_encode_der,
+	SET_OF_decode_xer,
+	SET_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_RelativeDistinguishedName_tags_1,
+	sizeof(asn_DEF_RelativeDistinguishedName_tags_1)
+		/sizeof(asn_DEF_RelativeDistinguishedName_tags_1[0]), /* 1 */
+	asn_DEF_RelativeDistinguishedName_tags_1,	/* Same as above */
+	sizeof(asn_DEF_RelativeDistinguishedName_tags_1)
+		/sizeof(asn_DEF_RelativeDistinguishedName_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_RelativeDistinguishedName_1,
+	1,	/* Single element */
+	&asn_SPC_RelativeDistinguishedName_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h b/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h
new file mode 100644
index 000000000000..48c906e258e9
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h
@@ -0,0 +1,44 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_RelativeDistinguishedName_H_
+#define	_RelativeDistinguishedName_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <asn_SET_OF.h>
+#include <constr_SET_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct AttributeValueAssertion;
+
+/* RelativeDistinguishedName */
+typedef struct RelativeDistinguishedName {
+	A_SET_OF(struct AttributeValueAssertion) list;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} RelativeDistinguishedName_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_RelativeDistinguishedName;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "AttributeValueAssertion.h"
+
+#endif	/* _RelativeDistinguishedName_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c b/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c
new file mode 100644
index 000000000000..4da761972db6
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c
@@ -0,0 +1,52 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "SetOfAuthenticatedAttribute.h"
+
+static asn_TYPE_member_t asn_MBR_SetOfAuthenticatedAttribute_1[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_AuthenticatedAttribute,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_SetOfAuthenticatedAttribute_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_SetOfAuthenticatedAttribute_specs_1 = {
+	sizeof(struct SetOfAuthenticatedAttribute),
+	offsetof(struct SetOfAuthenticatedAttribute, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_SetOfAuthenticatedAttribute = {
+	"SetOfAuthenticatedAttribute",
+	"SetOfAuthenticatedAttribute",
+	SET_OF_free,
+	SET_OF_print,
+	SET_OF_constraint,
+	SET_OF_decode_ber,
+	SET_OF_encode_der,
+	SET_OF_decode_xer,
+	SET_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_SetOfAuthenticatedAttribute_tags_1,
+	sizeof(asn_DEF_SetOfAuthenticatedAttribute_tags_1)
+		/sizeof(asn_DEF_SetOfAuthenticatedAttribute_tags_1[0]), /* 1 */
+	asn_DEF_SetOfAuthenticatedAttribute_tags_1,	/* Same as above */
+	sizeof(asn_DEF_SetOfAuthenticatedAttribute_tags_1)
+		/sizeof(asn_DEF_SetOfAuthenticatedAttribute_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_SetOfAuthenticatedAttribute_1,
+	1,	/* Single element */
+	&asn_SPC_SetOfAuthenticatedAttribute_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h b/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h
new file mode 100644
index 000000000000..65d1d57e8cc6
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h
@@ -0,0 +1,44 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_SetOfAuthenticatedAttribute_H_
+#define	_SetOfAuthenticatedAttribute_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <asn_SET_OF.h>
+#include <constr_SET_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+struct AuthenticatedAttribute;
+
+/* SetOfAuthenticatedAttribute */
+typedef struct SetOfAuthenticatedAttribute {
+	A_SET_OF(struct AuthenticatedAttribute) list;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} SetOfAuthenticatedAttribute_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_SetOfAuthenticatedAttribute;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "AuthenticatedAttribute.h"
+
+#endif	/* _SetOfAuthenticatedAttribute_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/SignedData.c b/libkmod/pkcs7/asn1c-gen/SignedData.c
new file mode 100644
index 000000000000..7db53fb3e6bb
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SignedData.c
@@ -0,0 +1,227 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "SignedData.h"
+
+static asn_TYPE_member_t asn_MBR_certificates_5[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct certificates, choice.certSet),
+		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_ExtendedCertificatesAndCertificates,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"certSet"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct certificates, choice.certSequence),
+		(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_Certificates,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"certSequence"
+		},
+};
+static const asn_TYPE_tag2member_t asn_MAP_certificates_tag2el_5[] = {
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* certSet */
+    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 } /* certSequence */
+};
+static asn_CHOICE_specifics_t asn_SPC_certificates_specs_5 = {
+	sizeof(struct certificates),
+	offsetof(struct certificates, _asn_ctx),
+	offsetof(struct certificates, present),
+	sizeof(((struct certificates *)0)->present),
+	asn_MAP_certificates_tag2el_5,
+	2,	/* Count of tags in the map */
+	0,
+	-1	/* Extensions start */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_certificates_5 = {
+	"certificates",
+	"certificates",
+	CHOICE_free,
+	CHOICE_print,
+	CHOICE_constraint,
+	CHOICE_decode_ber,
+	CHOICE_encode_der,
+	CHOICE_decode_xer,
+	CHOICE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	CHOICE_outmost_tag,
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	0,	/* No PER visible constraints */
+	asn_MBR_certificates_5,
+	2,	/* Elements count */
+	&asn_SPC_certificates_specs_5	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_crls_8[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct crls, choice.crlSet),
+		(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_CertificateRevocationLists,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"crlSet"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct crls, choice.crlSequence),
+		(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_CRLSequence,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"crlSequence"
+		},
+};
+static const asn_TYPE_tag2member_t asn_MAP_crls_tag2el_8[] = {
+    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* crlSet */
+    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 1, 0, 0 } /* crlSequence */
+};
+static asn_CHOICE_specifics_t asn_SPC_crls_specs_8 = {
+	sizeof(struct crls),
+	offsetof(struct crls, _asn_ctx),
+	offsetof(struct crls, present),
+	sizeof(((struct crls *)0)->present),
+	asn_MAP_crls_tag2el_8,
+	2,	/* Count of tags in the map */
+	0,
+	-1	/* Extensions start */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_crls_8 = {
+	"crls",
+	"crls",
+	CHOICE_free,
+	CHOICE_print,
+	CHOICE_constraint,
+	CHOICE_decode_ber,
+	CHOICE_encode_der,
+	CHOICE_decode_xer,
+	CHOICE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	CHOICE_outmost_tag,
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	0,	/* No PER visible constraints */
+	asn_MBR_crls_8,
+	2,	/* Elements count */
+	&asn_SPC_crls_specs_8	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_SignedData_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct SignedData, version),
+		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
+		0,
+		&asn_DEF_INTEGER,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"version"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SignedData, digestAlgorithms),
+		-1 /* Ambiguous tag (CHOICE?) */,
+		0,
+		&asn_DEF_DigestAlgorithmIdentifiers,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"digestAlgorithms"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SignedData, contentInfo),
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_ContentInfo,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"contentInfo"
+		},
+	{ ATF_POINTER, 2, offsetof(struct SignedData, certificates),
+		-1 /* Ambiguous tag (CHOICE?) */,
+		0,
+		&asn_DEF_certificates_5,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"certificates"
+		},
+	{ ATF_POINTER, 1, offsetof(struct SignedData, crls),
+		-1 /* Ambiguous tag (CHOICE?) */,
+		0,
+		&asn_DEF_crls_8,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"crls"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SignedData, signerInfos),
+		-1 /* Ambiguous tag (CHOICE?) */,
+		0,
+		&asn_DEF_SignerInfos,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"signerInfos"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_SignedData_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_SignedData_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* version */
+    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 2 }, /* daSequence */
+    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 2, -1, 1 }, /* contentInfo */
+    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 5, -2, 0 }, /* siSequence */
+    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 1, 0, 1 }, /* daSet */
+    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 5, -1, 0 }, /* siSet */
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 3, 0, 0 }, /* certSet */
+    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 4, 0, 0 }, /* crlSet */
+    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 3, 0, 0 }, /* certSequence */
+    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 4, 0, 0 } /* crlSequence */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_SignedData_specs_1 = {
+	sizeof(struct SignedData),
+	offsetof(struct SignedData, _asn_ctx),
+	asn_MAP_SignedData_tag2el_1,
+	10,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_SignedData = {
+	"SignedData",
+	"SignedData",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_SignedData_tags_1,
+	sizeof(asn_DEF_SignedData_tags_1)
+		/sizeof(asn_DEF_SignedData_tags_1[0]), /* 1 */
+	asn_DEF_SignedData_tags_1,	/* Same as above */
+	sizeof(asn_DEF_SignedData_tags_1)
+		/sizeof(asn_DEF_SignedData_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_SignedData_1,
+	6,	/* Elements count */
+	&asn_SPC_SignedData_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/SignedData.h b/libkmod/pkcs7/asn1c-gen/SignedData.h
new file mode 100644
index 000000000000..7e92bca95e69
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SignedData.h
@@ -0,0 +1,81 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_SignedData_H_
+#define	_SignedData_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include "DigestAlgorithmIdentifiers.h"
+#include "ContentInfo.h"
+#include "SignerInfos.h"
+#include "ExtendedCertificatesAndCertificates.h"
+#include "Certificates.h"
+#include <constr_CHOICE.h>
+#include "CertificateRevocationLists.h"
+#include "CRLSequence.h"
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Dependencies */
+typedef enum certificates_PR {
+	certificates_PR_NOTHING,	/* No components present */
+	certificates_PR_certSet,
+	certificates_PR_certSequence
+} certificates_PR;
+typedef enum crls_PR {
+	crls_PR_NOTHING,	/* No components present */
+	crls_PR_crlSet,
+	crls_PR_crlSequence
+} crls_PR;
+
+/* SignedData */
+typedef struct SignedData {
+	INTEGER_t	 version;
+	DigestAlgorithmIdentifiers_t	 digestAlgorithms;
+	ContentInfo_t	 contentInfo;
+	struct certificates {
+		certificates_PR present;
+		union SignedData__certificates_u {
+			ExtendedCertificatesAndCertificates_t	 certSet;
+			Certificates_t	 certSequence;
+		} choice;
+		
+		/* Context for parsing across buffer boundaries */
+		asn_struct_ctx_t _asn_ctx;
+	} *certificates;
+	struct crls {
+		crls_PR present;
+		union SignedData__crls_u {
+			CertificateRevocationLists_t	 crlSet;
+			CRLSequence_t	 crlSequence;
+		} choice;
+		
+		/* Context for parsing across buffer boundaries */
+		asn_struct_ctx_t _asn_ctx;
+	} *crls;
+	SignerInfos_t	 signerInfos;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} SignedData_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_SignedData;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _SignedData_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/SignerIdentifier.c b/libkmod/pkcs7/asn1c-gen/SignerIdentifier.c
new file mode 100644
index 000000000000..bb5e3e25e4ed
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SignerIdentifier.c
@@ -0,0 +1,65 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "SignerIdentifier.h"
+
+static asn_TYPE_member_t asn_MBR_SignerIdentifier_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct SignerIdentifier, choice.issuerAndSerialNumber),
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_IssuerAndSerialNumber,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"issuerAndSerialNumber"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SignerIdentifier, choice.subjectKeyIdentifier),
+		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_SubjectKeyIdentifier,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"subjectKeyIdentifier"
+		},
+};
+static const asn_TYPE_tag2member_t asn_MAP_SignerIdentifier_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 0, 0, 0 }, /* issuerAndSerialNumber */
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, 0, 0 } /* subjectKeyIdentifier */
+};
+static asn_CHOICE_specifics_t asn_SPC_SignerIdentifier_specs_1 = {
+	sizeof(struct SignerIdentifier),
+	offsetof(struct SignerIdentifier, _asn_ctx),
+	offsetof(struct SignerIdentifier, present),
+	sizeof(((struct SignerIdentifier *)0)->present),
+	asn_MAP_SignerIdentifier_tag2el_1,
+	2,	/* Count of tags in the map */
+	0,
+	-1	/* Extensions start */
+};
+asn_TYPE_descriptor_t asn_DEF_SignerIdentifier = {
+	"SignerIdentifier",
+	"SignerIdentifier",
+	CHOICE_free,
+	CHOICE_print,
+	CHOICE_constraint,
+	CHOICE_decode_ber,
+	CHOICE_encode_der,
+	CHOICE_decode_xer,
+	CHOICE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	CHOICE_outmost_tag,
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	0,	/* No PER visible constraints */
+	asn_MBR_SignerIdentifier_1,
+	2,	/* Elements count */
+	&asn_SPC_SignerIdentifier_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/SignerIdentifier.h b/libkmod/pkcs7/asn1c-gen/SignerIdentifier.h
new file mode 100644
index 000000000000..7eb253e5673d
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SignerIdentifier.h
@@ -0,0 +1,50 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_SignerIdentifier_H_
+#define	_SignerIdentifier_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include "IssuerAndSerialNumber.h"
+#include "SubjectKeyIdentifier.h"
+#include <constr_CHOICE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Dependencies */
+typedef enum SignerIdentifier_PR {
+	SignerIdentifier_PR_NOTHING,	/* No components present */
+	SignerIdentifier_PR_issuerAndSerialNumber,
+	SignerIdentifier_PR_subjectKeyIdentifier
+} SignerIdentifier_PR;
+
+/* SignerIdentifier */
+typedef struct SignerIdentifier {
+	SignerIdentifier_PR present;
+	union SignerIdentifier_u {
+		IssuerAndSerialNumber_t	 issuerAndSerialNumber;
+		SubjectKeyIdentifier_t	 subjectKeyIdentifier;
+	} choice;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} SignerIdentifier_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_SignerIdentifier;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _SignerIdentifier_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/SignerInfo.c b/libkmod/pkcs7/asn1c-gen/SignerInfo.c
new file mode 100644
index 000000000000..8e32418c2f63
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SignerInfo.c
@@ -0,0 +1,371 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "SignerInfo.h"
+
+static asn_TYPE_member_t asn_MBR_aaSequence_7[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_AuthenticatedAttribute,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_aaSequence_tags_7[] = {
+	(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_aaSequence_specs_7 = {
+	sizeof(struct aaSequence),
+	offsetof(struct aaSequence, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_aaSequence_7 = {
+	"aaSequence",
+	"aaSequence",
+	SEQUENCE_OF_free,
+	SEQUENCE_OF_print,
+	SEQUENCE_OF_constraint,
+	SEQUENCE_OF_decode_ber,
+	SEQUENCE_OF_encode_der,
+	SEQUENCE_OF_decode_xer,
+	SEQUENCE_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_aaSequence_tags_7,
+	sizeof(asn_DEF_aaSequence_tags_7)
+		/sizeof(asn_DEF_aaSequence_tags_7[0]), /* 2 */
+	asn_DEF_aaSequence_tags_7,	/* Same as above */
+	sizeof(asn_DEF_aaSequence_tags_7)
+		/sizeof(asn_DEF_aaSequence_tags_7[0]), /* 2 */
+	0,	/* No PER visible constraints */
+	asn_MBR_aaSequence_7,
+	1,	/* Single element */
+	&asn_SPC_aaSequence_specs_7	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_authenticatedAttributes_5[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct authenticatedAttributes, choice.aaSet),
+		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+		-1,	/* IMPLICIT tag at current level */
+		&asn_DEF_SetOfAuthenticatedAttribute,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"aaSet"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct authenticatedAttributes, choice.aaSequence),
+		(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
+		0,
+		&asn_DEF_aaSequence_7,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"aaSequence"
+		},
+};
+static const asn_TYPE_tag2member_t asn_MAP_authenticatedAttributes_tag2el_5[] = {
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* aaSet */
+    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 } /* aaSequence */
+};
+static asn_CHOICE_specifics_t asn_SPC_authenticatedAttributes_specs_5 = {
+	sizeof(struct authenticatedAttributes),
+	offsetof(struct authenticatedAttributes, _asn_ctx),
+	offsetof(struct authenticatedAttributes, present),
+	sizeof(((struct authenticatedAttributes *)0)->present),
+	asn_MAP_authenticatedAttributes_tag2el_5,
+	2,	/* Count of tags in the map */
+	0,
+	-1	/* Extensions start */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_authenticatedAttributes_5 = {
+	"authenticatedAttributes",
+	"authenticatedAttributes",
+	CHOICE_free,
+	CHOICE_print,
+	CHOICE_constraint,
+	CHOICE_decode_ber,
+	CHOICE_encode_der,
+	CHOICE_decode_xer,
+	CHOICE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	CHOICE_outmost_tag,
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	0,	/* No PER visible constraints */
+	asn_MBR_authenticatedAttributes_5,
+	2,	/* Elements count */
+	&asn_SPC_authenticatedAttributes_specs_5	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_uaSet_12[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_UnauthenticatedAttribute,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_uaSet_tags_12[] = {
+	(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_uaSet_specs_12 = {
+	sizeof(struct uaSet),
+	offsetof(struct uaSet, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_uaSet_12 = {
+	"uaSet",
+	"uaSet",
+	SET_OF_free,
+	SET_OF_print,
+	SET_OF_constraint,
+	SET_OF_decode_ber,
+	SET_OF_encode_der,
+	SET_OF_decode_xer,
+	SET_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_uaSet_tags_12,
+	sizeof(asn_DEF_uaSet_tags_12)
+		/sizeof(asn_DEF_uaSet_tags_12[0]) - 1, /* 1 */
+	asn_DEF_uaSet_tags_12,	/* Same as above */
+	sizeof(asn_DEF_uaSet_tags_12)
+		/sizeof(asn_DEF_uaSet_tags_12[0]), /* 2 */
+	0,	/* No PER visible constraints */
+	asn_MBR_uaSet_12,
+	1,	/* Single element */
+	&asn_SPC_uaSet_specs_12	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_uaSequence_14[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_UnauthenticatedAttribute,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_uaSequence_tags_14[] = {
+	(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_uaSequence_specs_14 = {
+	sizeof(struct uaSequence),
+	offsetof(struct uaSequence, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_uaSequence_14 = {
+	"uaSequence",
+	"uaSequence",
+	SEQUENCE_OF_free,
+	SEQUENCE_OF_print,
+	SEQUENCE_OF_constraint,
+	SEQUENCE_OF_decode_ber,
+	SEQUENCE_OF_encode_der,
+	SEQUENCE_OF_decode_xer,
+	SEQUENCE_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_uaSequence_tags_14,
+	sizeof(asn_DEF_uaSequence_tags_14)
+		/sizeof(asn_DEF_uaSequence_tags_14[0]) - 1, /* 1 */
+	asn_DEF_uaSequence_tags_14,	/* Same as above */
+	sizeof(asn_DEF_uaSequence_tags_14)
+		/sizeof(asn_DEF_uaSequence_tags_14[0]), /* 2 */
+	0,	/* No PER visible constraints */
+	asn_MBR_uaSequence_14,
+	1,	/* Single element */
+	&asn_SPC_uaSequence_specs_14	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_unauthenticatedAttributes_11[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct unauthenticatedAttributes, choice.uaSet),
+		(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+		0,
+		&asn_DEF_uaSet_12,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"uaSet"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct unauthenticatedAttributes, choice.uaSequence),
+		(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
+		0,
+		&asn_DEF_uaSequence_14,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"uaSequence"
+		},
+};
+static const asn_TYPE_tag2member_t asn_MAP_unauthenticatedAttributes_tag2el_11[] = {
+    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* uaSet */
+    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 1, 0, 0 } /* uaSequence */
+};
+static asn_CHOICE_specifics_t asn_SPC_unauthenticatedAttributes_specs_11 = {
+	sizeof(struct unauthenticatedAttributes),
+	offsetof(struct unauthenticatedAttributes, _asn_ctx),
+	offsetof(struct unauthenticatedAttributes, present),
+	sizeof(((struct unauthenticatedAttributes *)0)->present),
+	asn_MAP_unauthenticatedAttributes_tag2el_11,
+	2,	/* Count of tags in the map */
+	0,
+	-1	/* Extensions start */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_unauthenticatedAttributes_11 = {
+	"unauthenticatedAttributes",
+	"unauthenticatedAttributes",
+	CHOICE_free,
+	CHOICE_print,
+	CHOICE_constraint,
+	CHOICE_decode_ber,
+	CHOICE_encode_der,
+	CHOICE_decode_xer,
+	CHOICE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	CHOICE_outmost_tag,
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	0,	/* No PER visible constraints */
+	asn_MBR_unauthenticatedAttributes_11,
+	2,	/* Elements count */
+	&asn_SPC_unauthenticatedAttributes_specs_11	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_SignerInfo_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo, version),
+		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
+		0,
+		&asn_DEF_INTEGER,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"version"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo, sid),
+		-1 /* Ambiguous tag (CHOICE?) */,
+		0,
+		&asn_DEF_SignerIdentifier,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"sid"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo, digestAlgorithm),
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_DigestAlgorithmIdentifier,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"digestAlgorithm"
+		},
+	{ ATF_POINTER, 1, offsetof(struct SignerInfo, authenticatedAttributes),
+		-1 /* Ambiguous tag (CHOICE?) */,
+		0,
+		&asn_DEF_authenticatedAttributes_5,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"authenticatedAttributes"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo, digestEncryptionAlgorithm),
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_DigestEncryptionAlgorithmIdentifier,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"digestEncryptionAlgorithm"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo, encryptedDigest),
+		(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)),
+		0,
+		&asn_DEF_EncryptedDigest,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"encryptedDigest"
+		},
+	{ ATF_POINTER, 1, offsetof(struct SignerInfo, unauthenticatedAttributes),
+		-1 /* Ambiguous tag (CHOICE?) */,
+		0,
+		&asn_DEF_unauthenticatedAttributes_11,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"unauthenticatedAttributes"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_SignerInfo_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_SignerInfo_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* version */
+    { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 5, 0, 0 }, /* encryptedDigest */
+    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 2 }, /* issuerAndSerialNumber */
+    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 2, -1, 1 }, /* digestAlgorithm */
+    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 4, -2, 0 }, /* digestEncryptionAlgorithm */
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, 0, 1 }, /* subjectKeyIdentifier */
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 3, -1, 0 }, /* aaSet */
+    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 6, 0, 0 }, /* uaSet */
+    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 3, 0, 0 }, /* aaSequence */
+    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 6, 0, 0 } /* uaSequence */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_SignerInfo_specs_1 = {
+	sizeof(struct SignerInfo),
+	offsetof(struct SignerInfo, _asn_ctx),
+	asn_MAP_SignerInfo_tag2el_1,
+	10,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_SignerInfo = {
+	"SignerInfo",
+	"SignerInfo",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_SignerInfo_tags_1,
+	sizeof(asn_DEF_SignerInfo_tags_1)
+		/sizeof(asn_DEF_SignerInfo_tags_1[0]), /* 1 */
+	asn_DEF_SignerInfo_tags_1,	/* Same as above */
+	sizeof(asn_DEF_SignerInfo_tags_1)
+		/sizeof(asn_DEF_SignerInfo_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_SignerInfo_1,
+	7,	/* Elements count */
+	&asn_SPC_SignerInfo_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/SignerInfo.h b/libkmod/pkcs7/asn1c-gen/SignerInfo.h
new file mode 100644
index 000000000000..1cc8c986ff4e
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SignerInfo.h
@@ -0,0 +1,107 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_SignerInfo_H_
+#define	_SignerInfo_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <INTEGER.h>
+#include "SignerIdentifier.h"
+#include "DigestAlgorithmIdentifier.h"
+#include "DigestEncryptionAlgorithmIdentifier.h"
+#include "EncryptedDigest.h"
+#include "SetOfAuthenticatedAttribute.h"
+#include <asn_SEQUENCE_OF.h>
+#include <constr_SEQUENCE_OF.h>
+#include <constr_CHOICE.h>
+#include <asn_SET_OF.h>
+#include <constr_SET_OF.h>
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Dependencies */
+typedef enum authenticatedAttributes_PR {
+	authenticatedAttributes_PR_NOTHING,	/* No components present */
+	authenticatedAttributes_PR_aaSet,
+	authenticatedAttributes_PR_aaSequence
+} authenticatedAttributes_PR;
+typedef enum unauthenticatedAttributes_PR {
+	unauthenticatedAttributes_PR_NOTHING,	/* No components present */
+	unauthenticatedAttributes_PR_uaSet,
+	unauthenticatedAttributes_PR_uaSequence
+} unauthenticatedAttributes_PR;
+
+/* Forward declarations */
+struct AuthenticatedAttribute;
+struct UnauthenticatedAttribute;
+
+/* SignerInfo */
+typedef struct SignerInfo {
+	INTEGER_t	 version;
+	SignerIdentifier_t	 sid;
+	DigestAlgorithmIdentifier_t	 digestAlgorithm;
+	struct authenticatedAttributes {
+		authenticatedAttributes_PR present;
+		union SignerInfo__authenticatedAttributes_u {
+			SetOfAuthenticatedAttribute_t	 aaSet;
+			struct aaSequence {
+				A_SEQUENCE_OF(struct AuthenticatedAttribute) list;
+				
+				/* Context for parsing across buffer boundaries */
+				asn_struct_ctx_t _asn_ctx;
+			} aaSequence;
+		} choice;
+		
+		/* Context for parsing across buffer boundaries */
+		asn_struct_ctx_t _asn_ctx;
+	} *authenticatedAttributes;
+	DigestEncryptionAlgorithmIdentifier_t	 digestEncryptionAlgorithm;
+	EncryptedDigest_t	 encryptedDigest;
+	struct unauthenticatedAttributes {
+		unauthenticatedAttributes_PR present;
+		union SignerInfo__unauthenticatedAttributes_u {
+			struct uaSet {
+				A_SET_OF(struct UnauthenticatedAttribute) list;
+				
+				/* Context for parsing across buffer boundaries */
+				asn_struct_ctx_t _asn_ctx;
+			} uaSet;
+			struct uaSequence {
+				A_SEQUENCE_OF(struct UnauthenticatedAttribute) list;
+				
+				/* Context for parsing across buffer boundaries */
+				asn_struct_ctx_t _asn_ctx;
+			} uaSequence;
+		} choice;
+		
+		/* Context for parsing across buffer boundaries */
+		asn_struct_ctx_t _asn_ctx;
+	} *unauthenticatedAttributes;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} SignerInfo_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_SignerInfo;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "AuthenticatedAttribute.h"
+#include "UnauthenticatedAttribute.h"
+
+#endif	/* _SignerInfo_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/SignerInfos.c b/libkmod/pkcs7/asn1c-gen/SignerInfos.c
new file mode 100644
index 000000000000..36e3ca444339
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SignerInfos.c
@@ -0,0 +1,153 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "SignerInfos.h"
+
+static asn_TYPE_member_t asn_MBR_siSet_2[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_SignerInfo,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_siSet_tags_2[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_siSet_specs_2 = {
+	sizeof(struct siSet),
+	offsetof(struct siSet, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_siSet_2 = {
+	"siSet",
+	"siSet",
+	SET_OF_free,
+	SET_OF_print,
+	SET_OF_constraint,
+	SET_OF_decode_ber,
+	SET_OF_encode_der,
+	SET_OF_decode_xer,
+	SET_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_siSet_tags_2,
+	sizeof(asn_DEF_siSet_tags_2)
+		/sizeof(asn_DEF_siSet_tags_2[0]), /* 1 */
+	asn_DEF_siSet_tags_2,	/* Same as above */
+	sizeof(asn_DEF_siSet_tags_2)
+		/sizeof(asn_DEF_siSet_tags_2[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_siSet_2,
+	1,	/* Single element */
+	&asn_SPC_siSet_specs_2	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_siSequence_4[] = {
+	{ ATF_POINTER, 0, 0,
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_SignerInfo,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_siSequence_tags_4[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_siSequence_specs_4 = {
+	sizeof(struct siSequence),
+	offsetof(struct siSequence, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_siSequence_4 = {
+	"siSequence",
+	"siSequence",
+	SEQUENCE_OF_free,
+	SEQUENCE_OF_print,
+	SEQUENCE_OF_constraint,
+	SEQUENCE_OF_decode_ber,
+	SEQUENCE_OF_encode_der,
+	SEQUENCE_OF_decode_xer,
+	SEQUENCE_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_siSequence_tags_4,
+	sizeof(asn_DEF_siSequence_tags_4)
+		/sizeof(asn_DEF_siSequence_tags_4[0]), /* 1 */
+	asn_DEF_siSequence_tags_4,	/* Same as above */
+	sizeof(asn_DEF_siSequence_tags_4)
+		/sizeof(asn_DEF_siSequence_tags_4[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_siSequence_4,
+	1,	/* Single element */
+	&asn_SPC_siSequence_specs_4	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_SignerInfos_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfos, choice.siSet),
+		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
+		0,
+		&asn_DEF_siSet_2,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"siSet"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfos, choice.siSequence),
+		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
+		0,
+		&asn_DEF_siSequence_4,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"siSequence"
+		},
+};
+static const asn_TYPE_tag2member_t asn_MAP_SignerInfos_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 0 }, /* siSequence */
+    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 0, 0, 0 } /* siSet */
+};
+static asn_CHOICE_specifics_t asn_SPC_SignerInfos_specs_1 = {
+	sizeof(struct SignerInfos),
+	offsetof(struct SignerInfos, _asn_ctx),
+	offsetof(struct SignerInfos, present),
+	sizeof(((struct SignerInfos *)0)->present),
+	asn_MAP_SignerInfos_tag2el_1,
+	2,	/* Count of tags in the map */
+	0,
+	-1	/* Extensions start */
+};
+asn_TYPE_descriptor_t asn_DEF_SignerInfos = {
+	"SignerInfos",
+	"SignerInfos",
+	CHOICE_free,
+	CHOICE_print,
+	CHOICE_constraint,
+	CHOICE_decode_ber,
+	CHOICE_encode_der,
+	CHOICE_decode_xer,
+	CHOICE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	CHOICE_outmost_tag,
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	0,	/* No PER visible constraints */
+	asn_MBR_SignerInfos_1,
+	2,	/* Elements count */
+	&asn_SPC_SignerInfos_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/SignerInfos.h b/libkmod/pkcs7/asn1c-gen/SignerInfos.h
new file mode 100644
index 000000000000..cc7014623883
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SignerInfos.h
@@ -0,0 +1,68 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_SignerInfos_H_
+#define	_SignerInfos_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <asn_SET_OF.h>
+#include <constr_SET_OF.h>
+#include <asn_SEQUENCE_OF.h>
+#include <constr_SEQUENCE_OF.h>
+#include <constr_CHOICE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Dependencies */
+typedef enum SignerInfos_PR {
+	SignerInfos_PR_NOTHING,	/* No components present */
+	SignerInfos_PR_siSet,
+	SignerInfos_PR_siSequence
+} SignerInfos_PR;
+
+/* Forward declarations */
+struct SignerInfo;
+
+/* SignerInfos */
+typedef struct SignerInfos {
+	SignerInfos_PR present;
+	union SignerInfos_u {
+		struct siSet {
+			A_SET_OF(struct SignerInfo) list;
+			
+			/* Context for parsing across buffer boundaries */
+			asn_struct_ctx_t _asn_ctx;
+		} siSet;
+		struct siSequence {
+			A_SEQUENCE_OF(struct SignerInfo) list;
+			
+			/* Context for parsing across buffer boundaries */
+			asn_struct_ctx_t _asn_ctx;
+		} siSequence;
+	} choice;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} SignerInfos_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_SignerInfos;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Referred external types */
+#include "SignerInfo.h"
+
+#endif	/* _SignerInfos_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c b/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c
new file mode 100644
index 000000000000..2bde5c462489
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c
@@ -0,0 +1,109 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "SubjectKeyIdentifier.h"
+
+int
+SubjectKeyIdentifier_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	/* Replace with underlying type checker */
+	td->check_constraints = asn_DEF_OCTET_STRING.check_constraints;
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+/*
+ * This type is implemented using OCTET_STRING,
+ * so here we adjust the DEF accordingly.
+ */
+static void
+SubjectKeyIdentifier_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
+	td->free_struct    = asn_DEF_OCTET_STRING.free_struct;
+	td->print_struct   = asn_DEF_OCTET_STRING.print_struct;
+	td->check_constraints = asn_DEF_OCTET_STRING.check_constraints;
+	td->ber_decoder    = asn_DEF_OCTET_STRING.ber_decoder;
+	td->der_encoder    = asn_DEF_OCTET_STRING.der_encoder;
+	td->xer_decoder    = asn_DEF_OCTET_STRING.xer_decoder;
+	td->xer_encoder    = asn_DEF_OCTET_STRING.xer_encoder;
+	td->uper_decoder   = asn_DEF_OCTET_STRING.uper_decoder;
+	td->uper_encoder   = asn_DEF_OCTET_STRING.uper_encoder;
+	if(!td->per_constraints)
+		td->per_constraints = asn_DEF_OCTET_STRING.per_constraints;
+	td->elements       = asn_DEF_OCTET_STRING.elements;
+	td->elements_count = asn_DEF_OCTET_STRING.elements_count;
+	td->specifics      = asn_DEF_OCTET_STRING.specifics;
+}
+
+void
+SubjectKeyIdentifier_free(asn_TYPE_descriptor_t *td,
+		void *struct_ptr, int contents_only) {
+	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
+	td->free_struct(td, struct_ptr, contents_only);
+}
+
+int
+SubjectKeyIdentifier_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
+		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
+	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
+	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
+}
+
+asn_dec_rval_t
+SubjectKeyIdentifier_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const void *bufptr, size_t size, int tag_mode) {
+	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
+	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
+}
+
+asn_enc_rval_t
+SubjectKeyIdentifier_encode_der(asn_TYPE_descriptor_t *td,
+		void *structure, int tag_mode, ber_tlv_tag_t tag,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
+	return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
+}
+
+asn_dec_rval_t
+SubjectKeyIdentifier_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **structure, const char *opt_mname, const void *bufptr, size_t size) {
+	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
+	return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
+}
+
+asn_enc_rval_t
+SubjectKeyIdentifier_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
+		int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
+	return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
+}
+
+static const ber_tlv_tag_t asn_DEF_SubjectKeyIdentifier_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_SubjectKeyIdentifier = {
+	"SubjectKeyIdentifier",
+	"SubjectKeyIdentifier",
+	SubjectKeyIdentifier_free,
+	SubjectKeyIdentifier_print,
+	SubjectKeyIdentifier_constraint,
+	SubjectKeyIdentifier_decode_ber,
+	SubjectKeyIdentifier_encode_der,
+	SubjectKeyIdentifier_decode_xer,
+	SubjectKeyIdentifier_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_SubjectKeyIdentifier_tags_1,
+	sizeof(asn_DEF_SubjectKeyIdentifier_tags_1)
+		/sizeof(asn_DEF_SubjectKeyIdentifier_tags_1[0]), /* 1 */
+	asn_DEF_SubjectKeyIdentifier_tags_1,	/* Same as above */
+	sizeof(asn_DEF_SubjectKeyIdentifier_tags_1)
+		/sizeof(asn_DEF_SubjectKeyIdentifier_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	0	/* No specifics */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h b/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h
new file mode 100644
index 000000000000..fb1d276adf3a
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_SubjectKeyIdentifier_H_
+#define	_SubjectKeyIdentifier_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <OCTET_STRING.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* SubjectKeyIdentifier */
+typedef OCTET_STRING_t	 SubjectKeyIdentifier_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_SubjectKeyIdentifier;
+asn_struct_free_f SubjectKeyIdentifier_free;
+asn_struct_print_f SubjectKeyIdentifier_print;
+asn_constr_check_f SubjectKeyIdentifier_constraint;
+ber_type_decoder_f SubjectKeyIdentifier_decode_ber;
+der_type_encoder_f SubjectKeyIdentifier_encode_der;
+xer_type_decoder_f SubjectKeyIdentifier_decode_xer;
+xer_type_encoder_f SubjectKeyIdentifier_encode_xer;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _SubjectKeyIdentifier_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c b/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c
new file mode 100644
index 000000000000..3a6b6548c85f
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c
@@ -0,0 +1,69 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "UnauthenticatedAttribute.h"
+
+static asn_TYPE_member_t asn_MBR_UnauthenticatedAttribute_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct UnauthenticatedAttribute, type),
+		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
+		0,
+		&asn_DEF_OBJECT_IDENTIFIER,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"type"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct UnauthenticatedAttribute, values),
+		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
+		0,
+		&asn_DEF_Values,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		"values"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_UnauthenticatedAttribute_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_UnauthenticatedAttribute_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /* type */
+    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 1, 0, 0 } /* values */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_UnauthenticatedAttribute_specs_1 = {
+	sizeof(struct UnauthenticatedAttribute),
+	offsetof(struct UnauthenticatedAttribute, _asn_ctx),
+	asn_MAP_UnauthenticatedAttribute_tag2el_1,
+	2,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_UnauthenticatedAttribute = {
+	"UnauthenticatedAttribute",
+	"UnauthenticatedAttribute",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_UnauthenticatedAttribute_tags_1,
+	sizeof(asn_DEF_UnauthenticatedAttribute_tags_1)
+		/sizeof(asn_DEF_UnauthenticatedAttribute_tags_1[0]), /* 1 */
+	asn_DEF_UnauthenticatedAttribute_tags_1,	/* Same as above */
+	sizeof(asn_DEF_UnauthenticatedAttribute_tags_1)
+		/sizeof(asn_DEF_UnauthenticatedAttribute_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_UnauthenticatedAttribute_1,
+	2,	/* Elements count */
+	&asn_SPC_UnauthenticatedAttribute_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h b/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h
new file mode 100644
index 000000000000..5837608b97ce
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h
@@ -0,0 +1,40 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_UnauthenticatedAttribute_H_
+#define	_UnauthenticatedAttribute_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <OBJECT_IDENTIFIER.h>
+#include "Values.h"
+#include <constr_SEQUENCE.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* UnauthenticatedAttribute */
+typedef struct UnauthenticatedAttribute {
+	OBJECT_IDENTIFIER_t	 type;
+	Values_t	 values;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} UnauthenticatedAttribute_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_UnauthenticatedAttribute;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _UnauthenticatedAttribute_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/Values.c b/libkmod/pkcs7/asn1c-gen/Values.c
new file mode 100644
index 000000000000..def8389e63d2
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Values.c
@@ -0,0 +1,52 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#include "Values.h"
+
+static asn_TYPE_member_t asn_MBR_Values_1[] = {
+	{ ATF_OPEN_TYPE | ATF_POINTER, 0, 0,
+		-1 /* Ambiguous tag (ANY?) */,
+		0,
+		&asn_DEF_ANY,
+		0,	/* Defer constraints checking to the member type */
+		0,	/* PER is not compiled, use -gen-PER */
+		0,
+		""
+		},
+};
+static const ber_tlv_tag_t asn_DEF_Values_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
+};
+static asn_SET_OF_specifics_t asn_SPC_Values_specs_1 = {
+	sizeof(struct Values),
+	offsetof(struct Values, _asn_ctx),
+	0,	/* XER encoding is XMLDelimitedItemList */
+};
+asn_TYPE_descriptor_t asn_DEF_Values = {
+	"Values",
+	"Values",
+	SET_OF_free,
+	SET_OF_print,
+	SET_OF_constraint,
+	SET_OF_decode_ber,
+	SET_OF_encode_der,
+	SET_OF_decode_xer,
+	SET_OF_encode_xer,
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_Values_tags_1,
+	sizeof(asn_DEF_Values_tags_1)
+		/sizeof(asn_DEF_Values_tags_1[0]), /* 1 */
+	asn_DEF_Values_tags_1,	/* Same as above */
+	sizeof(asn_DEF_Values_tags_1)
+		/sizeof(asn_DEF_Values_tags_1[0]), /* 1 */
+	0,	/* No PER visible constraints */
+	asn_MBR_Values_1,
+	1,	/* Single element */
+	&asn_SPC_Values_specs_1	/* Additional specs */
+};
+
diff --git a/libkmod/pkcs7/asn1c-gen/Values.h b/libkmod/pkcs7/asn1c-gen/Values.h
new file mode 100644
index 000000000000..8328a1163cac
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/Values.h
@@ -0,0 +1,39 @@
+/*
+ * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
+ * From ASN.1 module "PKCS7"
+ * 	found in "../pkcs7.asn1"
+ * 	`asn1c -fwide-types`
+ */
+
+#ifndef	_Values_H_
+#define	_Values_H_
+
+
+#include <asn_application.h>
+
+/* Including external dependencies */
+#include <ANY.h>
+#include <asn_SET_OF.h>
+#include <constr_SET_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Values */
+typedef struct Values {
+	A_SET_OF(ANY_t) list;
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} Values_t;
+
+/* Implementation */
+extern asn_TYPE_descriptor_t asn_DEF_Values;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _Values_H_ */
+#include <asn_internal.h>
diff --git a/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c b/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c
new file mode 100644
index 000000000000..ec952fc99936
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <asn_SEQUENCE_OF.h>
+
+typedef A_SEQUENCE_OF(void) asn_sequence;
+
+void
+asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free) {
+	asn_sequence *as = (asn_sequence *)asn_sequence_of_x;
+
+	if(as) {
+		void *ptr;
+		int n;
+
+		if(number < 0 || number >= as->count)
+			return;	/* Nothing to delete */
+
+		if(_do_free && as->free) {
+			ptr = as->array[number];
+		} else {
+			ptr = 0;
+		}
+
+		/*
+		 * Shift all elements to the left to hide the gap.
+		 */
+		--as->count;
+		for(n = number; n < as->count; n++)
+			as->array[n] = as->array[n+1];
+
+		/*
+		 * Invoke the third-party function only when the state
+		 * of the parent structure is consistent.
+		 */
+		if(ptr) as->free(ptr);
+	}
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h b/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h
new file mode 100644
index 000000000000..e678f0347221
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	ASN_SEQUENCE_OF_H
+#define	ASN_SEQUENCE_OF_H
+
+#include <asn_SET_OF.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * SEQUENCE OF is the same as SET OF with a tiny difference:
+ * the delete operation preserves the initial order of elements
+ * and thus MAY operate in non-constant time.
+ */
+#define	A_SEQUENCE_OF(type)	A_SET_OF(type)
+
+#define	ASN_SEQUENCE_ADD(headptr, ptr)		\
+	asn_sequence_add((headptr), (ptr))
+
+/***********************************************
+ * Implementation of the SEQUENCE OF structure.
+ */
+
+#define	asn_sequence_add	asn_set_add
+#define	asn_sequence_empty	asn_set_empty
+
+/*
+ * Delete the element from the set by its number (base 0).
+ * This is NOT a constant-time operation.
+ * The order of elements is preserved.
+ * If _do_free is given AND the (*free) is initialized, the element
+ * will be freed using the custom (*free) function as well.
+ */
+void asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free);
+
+/*
+ * Cope with different conversions requirements to/from void in C and C++.
+ * This is mostly useful for support library.
+ */
+typedef A_SEQUENCE_OF(void) asn_anonymous_sequence_;
+#define _A_SEQUENCE_FROM_VOID(ptr)	((asn_anonymous_sequence_ *)(ptr))
+#define _A_CSEQUENCE_FROM_VOID(ptr) 	((const asn_anonymous_sequence_ *)(ptr))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ASN_SEQUENCE_OF_H */
diff --git a/libkmod/pkcs7/asn1c-gen/asn_SET_OF.c b/libkmod/pkcs7/asn1c-gen/asn_SET_OF.c
new file mode 100644
index 000000000000..944f2cb8ad70
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_SET_OF.c
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <asn_SET_OF.h>
+#include <errno.h>
+
+/*
+ * Add another element into the set.
+ */
+int
+asn_set_add(void *asn_set_of_x, void *ptr) {
+	asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
+
+	if(as == 0 || ptr == 0) {
+		errno = EINVAL;		/* Invalid arguments */
+		return -1;
+	}
+
+	/*
+	 * Make sure there's enough space to insert an element.
+	 */
+	if(as->count == as->size) {
+		int _newsize = as->size ? (as->size << 1) : 4;
+		void *_new_arr;
+		_new_arr = REALLOC(as->array, _newsize * sizeof(as->array[0]));
+		if(_new_arr) {
+			as->array = (void **)_new_arr;
+			as->size = _newsize;
+		} else {
+			/* ENOMEM */
+			return -1;
+		}
+	}
+
+	as->array[as->count++] = ptr;
+
+	return 0;
+}
+
+void
+asn_set_del(void *asn_set_of_x, int number, int _do_free) {
+	asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
+
+	if(as) {
+		void *ptr;
+		if(number < 0 || number >= as->count)
+			return;
+
+		if(_do_free && as->free) {
+			ptr = as->array[number];
+		} else {
+			ptr = 0;
+		}
+
+		as->array[number] = as->array[--as->count];
+
+		/*
+		 * Invoke the third-party function only when the state
+		 * of the parent structure is consistent.
+		 */
+		if(ptr) as->free(ptr);
+	}
+}
+
+/*
+ * Free the contents of the set, do not free the set itself.
+ */
+void
+asn_set_empty(void *asn_set_of_x) {
+	asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
+
+	if(as) {
+		if(as->array) {
+			if(as->free) {
+				while(as->count--)
+					as->free(as->array[as->count]);
+			}
+			FREEMEM(as->array);
+			as->array = 0;
+		}
+		as->count = 0;
+		as->size = 0;
+	}
+
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/asn_SET_OF.h b/libkmod/pkcs7/asn1c-gen/asn_SET_OF.h
new file mode 100644
index 000000000000..7edf14b51b98
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_SET_OF.h
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	ASN_SET_OF_H
+#define	ASN_SET_OF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define	A_SET_OF(type)					\
+	struct {					\
+		type **array;				\
+		int count;	/* Meaningful size */	\
+		int size;	/* Allocated size */	\
+		void (*free)(type *);			\
+	}
+
+#define	ASN_SET_ADD(headptr, ptr)		\
+	asn_set_add((headptr), (ptr))
+
+/*******************************************
+ * Implementation of the SET OF structure.
+ */
+
+/*
+ * Add another structure into the set by its pointer.
+ * RETURN VALUES:
+ * 0 for success and -1/errno for failure.
+ */
+int  asn_set_add(void *asn_set_of_x, void *ptr);
+
+/*
+ * Delete the element from the set by its number (base 0).
+ * This is a constant-time operation. The order of elements before the
+ * deleted ones is guaranteed, the order of elements after the deleted
+ * one is NOT guaranteed.
+ * If _do_free is given AND the (*free) is initialized, the element
+ * will be freed using the custom (*free) function as well.
+ */
+void asn_set_del(void *asn_set_of_x, int number, int _do_free);
+
+/*
+ * Empty the contents of the set. Will free the elements, if (*free) is given.
+ * Will NOT free the set itself.
+ */
+void asn_set_empty(void *asn_set_of_x);
+
+/*
+ * Cope with different conversions requirements to/from void in C and C++.
+ * This is mostly useful for support library.
+ */
+typedef A_SET_OF(void) asn_anonymous_set_;
+#define _A_SET_FROM_VOID(ptr)		((asn_anonymous_set_ *)(ptr))
+#define _A_CSET_FROM_VOID(ptr)		((const asn_anonymous_set_ *)(ptr))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ASN_SET_OF_H */
diff --git a/libkmod/pkcs7/asn1c-gen/asn_application.h b/libkmod/pkcs7/asn1c-gen/asn_application.h
new file mode 100644
index 000000000000..71e9ba61b2e8
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_application.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+/*
+ * Application-level ASN.1 callbacks.
+ */
+#ifndef	ASN_APPLICATION_H
+#define	ASN_APPLICATION_H
+
+#include "asn_system.h"		/* for platform-dependent types */
+#include "asn_codecs.h"		/* for ASN.1 codecs specifics */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Generic type of an application-defined callback to return various
+ * types of data to the application.
+ * EXPECTED RETURN VALUES:
+ *  -1: Failed to consume bytes. Abort the mission.
+ * Non-negative return values indicate success, and ignored.
+ */
+typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t size,
+	void *application_specific_key);
+
+/*
+ * A callback of this type is called whenever constraint validation fails
+ * on some ASN.1 type. See "constraints.h" for more details on constraint
+ * validation.
+ * This callback specifies a descriptor of the ASN.1 type which failed
+ * the constraint check, as well as human readable message on what
+ * particular constraint has failed.
+ */
+typedef void (asn_app_constraint_failed_f)(void *application_specific_key,
+	struct asn_TYPE_descriptor_s *type_descriptor_which_failed,
+	const void *structure_which_failed_ptr,
+	const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5);
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "constr_TYPE.h"	/* for asn_TYPE_descriptor_t */
+
+#endif	/* ASN_APPLICATION_H */
diff --git a/libkmod/pkcs7/asn1c-gen/asn_codecs.h b/libkmod/pkcs7/asn1c-gen/asn_codecs.h
new file mode 100644
index 000000000000..4b2a294293c2
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_codecs.h
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	ASN_CODECS_H
+#define	ASN_CODECS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;	/* Forward declaration */
+
+/*
+ * This structure defines a set of parameters that may be passed
+ * to every ASN.1 encoder or decoder function.
+ * WARNING: if max_stack_size member is set, and you are calling the
+ *   function pointers of the asn_TYPE_descriptor_t directly,
+ *   this structure must be ALLOCATED ON THE STACK!
+ *   If you can't always satisfy this requirement, use ber_decode(),
+ *   xer_decode() and uper_decode() functions instead.
+ */
+typedef struct asn_codec_ctx_s {
+	/*
+	 * Limit the decoder routines to use no (much) more stack than a given
+	 * number of bytes. Most of decoders are stack-based, and this
+	 * would protect against stack overflows if the number of nested
+	 * encodings is high.
+	 * The OCTET STRING, BIT STRING and ANY BER decoders are heap-based,
+	 * and are safe from this kind of overflow.
+	 * A value from getrlimit(RLIMIT_STACK) may be used to initialize
+	 * this variable. Be careful in multithreaded environments, as the
+	 * stack size is rather limited.
+	 */
+	size_t  max_stack_size; /* 0 disables stack bounds checking */
+} asn_codec_ctx_t;
+
+/*
+ * Type of the return value of the encoding functions (der_encode, xer_encode).
+ */
+typedef struct asn_enc_rval_s {
+	/*
+	 * Number of bytes encoded.
+	 * -1 indicates failure to encode the structure.
+	 * In this case, the members below this one are meaningful.
+	 */
+	ssize_t encoded;
+
+	/*
+	 * Members meaningful when (encoded == -1), for post mortem analysis.
+	 */
+
+	/* Type which cannot be encoded */
+	struct asn_TYPE_descriptor_s *failed_type;
+
+	/* Pointer to the structure of that type */
+	void *structure_ptr;
+} asn_enc_rval_t;
+#define	ASN__ENCODE_FAILED do {					\
+	asn_enc_rval_t tmp_error;				\
+	tmp_error.encoded = -1;					\
+	tmp_error.failed_type = td;				\
+	tmp_error.structure_ptr = sptr;				\
+	ASN_DEBUG("Failed to encode element %s", td ? td->name : "");	\
+	return tmp_error;					\
+} while(0)
+#define	ASN__ENCODED_OK(rval) do {				\
+	rval.structure_ptr = 0;					\
+	rval.failed_type = 0;					\
+	return rval;						\
+} while(0)
+
+/*
+ * Type of the return value of the decoding functions (ber_decode, xer_decode)
+ * 
+ * Please note that the number of consumed bytes is ALWAYS meaningful,
+ * even if code==RC_FAIL. This is to indicate the number of successfully
+ * decoded bytes, hence providing a possibility to fail with more diagnostics
+ * (i.e., print the offending remainder of the buffer).
+ */
+enum asn_dec_rval_code_e {
+	RC_OK,		/* Decoded successfully */
+	RC_WMORE,	/* More data expected, call again */
+	RC_FAIL		/* Failure to decode data */
+};
+typedef struct asn_dec_rval_s {
+	enum asn_dec_rval_code_e code;	/* Result code */
+	size_t consumed;		/* Number of bytes consumed */
+} asn_dec_rval_t;
+#define	ASN__DECODE_FAILED do {					\
+	asn_dec_rval_t tmp_error;				\
+	tmp_error.code = RC_FAIL;				\
+	tmp_error.consumed = 0;					\
+	ASN_DEBUG("Failed to decode element %s", td ? td->name : "");	\
+	return tmp_error;					\
+} while(0)
+#define	ASN__DECODE_STARVED do {				\
+	asn_dec_rval_t tmp_error;				\
+	tmp_error.code = RC_WMORE;				\
+	tmp_error.consumed = 0;					\
+	return tmp_error;					\
+} while(0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ASN_CODECS_H */
diff --git a/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c b/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c
new file mode 100644
index 000000000000..426339c94fa9
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c
@@ -0,0 +1,312 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <asn_codecs_prim.h>
+#include <errno.h>
+
+/*
+ * Decode an always-primitive type.
+ */
+asn_dec_rval_t
+ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td,
+	void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
+	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
+	asn_dec_rval_t rval;
+	ber_tlv_len_t length = 0; /* =0 to avoid [incorrect] warning. */
+
+	/*
+	 * If the structure is not there, allocate it.
+	 */
+	if(st == NULL) {
+		st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
+		if(st == NULL) ASN__DECODE_FAILED;
+		*sptr = (void *)st;
+	}
+
+	ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
+		td->name, tag_mode);
+
+	/*
+	 * Check tags and extract value length.
+	 */
+	rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
+			tag_mode, 0, &length, 0);
+	if(rval.code != RC_OK)
+		return rval;
+
+	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
+
+	/*
+	 * Make sure we have this length.
+	 */
+	buf_ptr = ((const char *)buf_ptr) + rval.consumed;
+	size -= rval.consumed;
+	if(length > (ber_tlv_len_t)size) {
+		rval.code = RC_WMORE;
+		rval.consumed = 0;
+		return rval;
+	}
+
+	st->size = (int)length;
+	/* The following better be optimized away. */
+	if(sizeof(st->size) != sizeof(length)
+			&& (ber_tlv_len_t)st->size != length) {
+		st->size = 0;
+		ASN__DECODE_FAILED;
+	}
+
+	st->buf = (uint8_t *)MALLOC(length + 1);
+	if(!st->buf) {
+		st->size = 0;
+		ASN__DECODE_FAILED;
+	}
+
+	memcpy(st->buf, buf_ptr, length);
+	st->buf[length] = '\0';		/* Just in case */
+
+	rval.code = RC_OK;
+	rval.consumed += length;
+
+	ASN_DEBUG("Took %ld/%ld bytes to encode %s",
+		(long)rval.consumed,
+		(long)length, td->name);
+
+	return rval;
+}
+
+/*
+ * Encode an always-primitive type using DER.
+ */
+asn_enc_rval_t
+der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
+	int tag_mode, ber_tlv_tag_t tag,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_enc_rval_t erval;
+	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
+
+	ASN_DEBUG("%s %s as a primitive type (tm=%d)",
+		cb?"Encoding":"Estimating", td->name, tag_mode);
+
+	erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
+		cb, app_key);
+	ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
+	if(erval.encoded == -1) {
+		erval.failed_type = td;
+		erval.structure_ptr = sptr;
+		return erval;
+	}
+
+	if(cb && st->buf) {
+		if(cb(st->buf, st->size, app_key) < 0) {
+			erval.encoded = -1;
+			erval.failed_type = td;
+			erval.structure_ptr = sptr;
+			return erval;
+		}
+	} else {
+		assert(st->buf || st->size == 0);
+	}
+
+	erval.encoded += st->size;
+	ASN__ENCODED_OK(erval);
+}
+
+void
+ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
+		int contents_only) {
+	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
+
+	if(!td || !sptr)
+		return;
+
+	ASN_DEBUG("Freeing %s as a primitive type", td->name);
+
+	if(st->buf)
+		FREEMEM(st->buf);
+
+	if(!contents_only)
+		FREEMEM(st);
+}
+
+
+/*
+ * Local internal type passed around as an argument.
+ */
+struct xdp_arg_s {
+	asn_TYPE_descriptor_t *type_descriptor;
+	void *struct_key;
+	xer_primitive_body_decoder_f *prim_body_decoder;
+	int decoded_something;
+	int want_more;
+};
+
+/*
+ * Since some kinds of primitive values can be encoded using value-specific
+ * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
+ * be supplied with such tags to parse them as needed.
+ */
+static int
+xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
+	struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
+	enum xer_pbd_rval bret;
+
+	/*
+	 * The chunk_buf is guaranteed to start at '<'.
+	 */
+	assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
+
+	/*
+	 * Decoding was performed once already. Prohibit doing it again.
+	 */
+	if(arg->decoded_something)
+		return -1;
+
+	bret = arg->prim_body_decoder(arg->type_descriptor,
+		arg->struct_key, chunk_buf, chunk_size);
+	switch(bret) {
+	case XPBD_SYSTEM_FAILURE:
+	case XPBD_DECODER_LIMIT:
+	case XPBD_BROKEN_ENCODING:
+		break;
+	case XPBD_BODY_CONSUMED:
+		/* Tag decoded successfully */
+		arg->decoded_something = 1;
+		/* Fall through */
+	case XPBD_NOT_BODY_IGNORE:	/* Safe to proceed further */
+		return 0;
+	}
+
+	return -1;
+}
+
+static ssize_t
+xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
+	struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
+	enum xer_pbd_rval bret;
+	size_t lead_wsp_size;
+
+	if(arg->decoded_something) {
+		if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
+			/*
+			 * Example:
+			 * "<INTEGER>123<!--/--> </INTEGER>"
+			 *                      ^- chunk_buf position.
+			 */
+			return chunk_size;
+		}
+		/*
+		 * Decoding was done once already. Prohibit doing it again.
+		 */
+		return -1;
+	}
+
+	if(!have_more) {
+		/*
+		 * If we've received something like "1", we can't really
+		 * tell whether it is really `1` or `123`, until we know
+		 * that there is no more data coming.
+		 * The have_more argument will be set to 1 once something
+		 * like this is available to the caller of this callback:
+		 * "1<tag_start..."
+		 */
+		arg->want_more = 1;
+		return -1;
+	}
+
+	lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
+	chunk_buf = (const char *)chunk_buf + lead_wsp_size;
+	chunk_size -= lead_wsp_size;
+
+	bret = arg->prim_body_decoder(arg->type_descriptor,
+		arg->struct_key, chunk_buf, chunk_size);
+	switch(bret) {
+	case XPBD_SYSTEM_FAILURE:
+	case XPBD_DECODER_LIMIT:
+	case XPBD_BROKEN_ENCODING:
+		break;
+	case XPBD_BODY_CONSUMED:
+		/* Tag decoded successfully */
+		arg->decoded_something = 1;
+		/* Fall through */
+	case XPBD_NOT_BODY_IGNORE:	/* Safe to proceed further */
+		return lead_wsp_size + chunk_size;
+	}
+
+	return -1;
+}
+
+
+asn_dec_rval_t
+xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *td,
+	void **sptr,
+	size_t struct_size,
+	const char *opt_mname,
+	const void *buf_ptr, size_t size,
+	xer_primitive_body_decoder_f *prim_body_decoder
+) {
+	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
+	asn_struct_ctx_t s_ctx;
+	struct xdp_arg_s s_arg;
+	asn_dec_rval_t rc;
+
+	/*
+	 * Create the structure if does not exist.
+	 */
+	if(!*sptr) {
+		*sptr = CALLOC(1, struct_size);
+		if(!*sptr) ASN__DECODE_FAILED;
+	}
+
+	memset(&s_ctx, 0, sizeof(s_ctx));
+	s_arg.type_descriptor = td;
+	s_arg.struct_key = *sptr;
+	s_arg.prim_body_decoder = prim_body_decoder;
+	s_arg.decoded_something = 0;
+	s_arg.want_more = 0;
+
+	rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
+		xml_tag, buf_ptr, size,
+		xer_decode__unexpected_tag, xer_decode__primitive_body);
+	switch(rc.code) {
+	case RC_OK:
+		if(!s_arg.decoded_something) {
+			char ch;
+			ASN_DEBUG("Primitive body is not recognized, "
+				"supplying empty one");
+			/*
+			 * Decoding opportunity has come and gone.
+			 * Where's the result?
+			 * Try to feed with empty body, see if it eats it.
+			 */
+			if(prim_body_decoder(s_arg.type_descriptor,
+				s_arg.struct_key, &ch, 0)
+					!= XPBD_BODY_CONSUMED) {
+				/*
+				 * This decoder does not like empty stuff.
+				 */
+				ASN__DECODE_FAILED;
+			}
+		}
+		break;
+	case RC_WMORE:
+		/*
+		 * Redo the whole thing later.
+		 * We don't have a context to save intermediate parsing state.
+		 */
+		rc.consumed = 0;
+		break;
+	case RC_FAIL:
+		rc.consumed = 0;
+		if(s_arg.want_more)
+			rc.code = RC_WMORE;
+		else
+			ASN__DECODE_FAILED;
+		break;
+	}
+	return rc;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h b/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h
new file mode 100644
index 000000000000..0f683fdd0ac7
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	ASN_CODECS_PRIM_H
+#define	ASN_CODECS_PRIM_H
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ASN__PRIMITIVE_TYPE_s {
+	uint8_t *buf;	/* Buffer with consecutive primitive encoding bytes */
+	int size;	/* Size of the buffer */
+} ASN__PRIMITIVE_TYPE_t;	/* Do not use this type directly! */
+
+asn_struct_free_f ASN__PRIMITIVE_TYPE_free;
+ber_type_decoder_f ber_decode_primitive;
+der_type_encoder_f der_encode_primitive;
+
+/*
+ * A callback specification for the xer_decode_primitive() function below.
+ */
+enum xer_pbd_rval {
+	XPBD_SYSTEM_FAILURE,	/* System failure (memory shortage, etc) */
+	XPBD_DECODER_LIMIT,	/* Hit some decoder limitation or deficiency */
+	XPBD_BROKEN_ENCODING,	/* Encoding of a primitive body is broken */
+	XPBD_NOT_BODY_IGNORE,	/* Not a body format, but safe to ignore */
+	XPBD_BODY_CONSUMED	/* Body is recognized and consumed */
+};
+typedef enum xer_pbd_rval (xer_primitive_body_decoder_f)
+	(asn_TYPE_descriptor_t *td, void *struct_ptr,
+		const void *chunk_buf, size_t chunk_size);
+
+/*
+ * Specific function to decode simple primitive types.
+ * Also see xer_decode_general() in xer_decoder.h
+ */
+asn_dec_rval_t xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *type_descriptor,
+	void **struct_ptr, size_t struct_size,
+	const char *opt_mname,
+	const void *buf_ptr, size_t size,
+	xer_primitive_body_decoder_f *prim_body_decoder
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ASN_CODECS_PRIM_H */
diff --git a/libkmod/pkcs7/asn1c-gen/asn_internal.h b/libkmod/pkcs7/asn1c-gen/asn_internal.h
new file mode 100644
index 000000000000..9c94ca6c3b77
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_internal.h
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 2003, 2004, 2005, 2007 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+/*
+ * Declarations internally useful for the ASN.1 support code.
+ */
+#ifndef	ASN_INTERNAL_H
+#define	ASN_INTERNAL_H
+
+#include "asn_application.h"	/* Application-visible API */
+
+#ifndef	__NO_ASSERT_H__		/* Include assert.h only for internal use. */
+#include <assert.h>		/* for assert() macro */
+#endif
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* Environment version might be used to avoid running with the old library */
+#define	ASN1C_ENVIRONMENT_VERSION	923	/* Compile-time version */
+int get_asn1c_environment_version(void);	/* Run-time version */
+
+#define	CALLOC(nmemb, size)	calloc(nmemb, size)
+#define	MALLOC(size)		malloc(size)
+#define	REALLOC(oldptr, size)	realloc(oldptr, size)
+#define	FREEMEM(ptr)		free(ptr)
+
+#define	asn_debug_indent	0
+#define ASN_DEBUG_INDENT_ADD(i) do{}while(0)
+
+/*
+ * A macro for debugging the ASN.1 internals.
+ * You may enable or override it.
+ */
+#ifndef	ASN_DEBUG	/* If debugging code is not defined elsewhere... */
+#if	EMIT_ASN_DEBUG == 1	/* And it was asked to emit this code... */
+#ifdef	__GNUC__
+#ifdef	ASN_THREAD_SAFE
+/* Thread safety requires sacrifice in output indentation:
+ * Retain empty definition of ASN_DEBUG_INDENT_ADD. */
+#else	/* !ASN_THREAD_SAFE */
+#undef  ASN_DEBUG_INDENT_ADD
+#undef  asn_debug_indent
+int asn_debug_indent;
+#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent += i; } while(0)
+#endif	/* ASN_THREAD_SAFE */
+#define	ASN_DEBUG(fmt, args...)	do {			\
+		int adi = asn_debug_indent;		\
+		while(adi--) fprintf(stderr, " ");	\
+		fprintf(stderr, fmt, ##args);		\
+		fprintf(stderr, " (%s:%d)\n",		\
+			__FILE__, __LINE__);		\
+	} while(0)
+#else	/* !__GNUC__ */
+void ASN_DEBUG_f(const char *fmt, ...);
+#define	ASN_DEBUG	ASN_DEBUG_f
+#endif	/* __GNUC__ */
+#else	/* EMIT_ASN_DEBUG != 1 */
+static void ASN_DEBUG(const char *fmt, ...) { (void)fmt; }
+#endif	/* EMIT_ASN_DEBUG */
+#endif	/* ASN_DEBUG */
+
+/*
+ * Invoke the application-supplied callback and fail, if something is wrong.
+ */
+#define	ASN__E_cbc(buf, size)	(cb((buf), (size), app_key) < 0)
+#define	ASN__E_CALLBACK(foo)	do {					\
+		if(foo)	goto cb_failed;					\
+	} while(0)
+#define	ASN__CALLBACK(buf, size)					\
+	ASN__E_CALLBACK(ASN__E_cbc(buf, size))
+#define	ASN__CALLBACK2(buf1, size1, buf2, size2)			\
+	ASN__E_CALLBACK(ASN__E_cbc(buf1, size1) || ASN__E_cbc(buf2, size2))
+#define	ASN__CALLBACK3(buf1, size1, buf2, size2, buf3, size3)		\
+	ASN__E_CALLBACK(ASN__E_cbc(buf1, size1)			\
+		|| ASN__E_cbc(buf2, size2)				\
+		|| ASN__E_cbc(buf3, size3))
+
+#define	ASN__TEXT_INDENT(nl, level) do {            \
+        int tmp_level = (level);                    \
+        int tmp_nl = ((nl) != 0);                   \
+        int tmp_i;                                  \
+        if(tmp_nl) ASN__CALLBACK("\n", 1);          \
+        if(tmp_level < 0) tmp_level = 0;            \
+        for(tmp_i = 0; tmp_i < tmp_level; tmp_i++)  \
+            ASN__CALLBACK("    ", 4);               \
+        er.encoded += tmp_nl + 4 * tmp_level;       \
+    } while(0)
+
+#define	_i_INDENT(nl)	do {                        \
+        int tmp_i;                                  \
+        if((nl) && cb("\n", 1, app_key) < 0)        \
+            return -1;                              \
+        for(tmp_i = 0; tmp_i < ilevel; tmp_i++)     \
+            if(cb("    ", 4, app_key) < 0)          \
+                return -1;                          \
+    } while(0)
+
+/*
+ * Check stack against overflow, if limit is set.
+ */
+#define	ASN__DEFAULT_STACK_MAX	(30000)
+static int __attribute__((unused))
+ASN__STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) {
+	if(ctx && ctx->max_stack_size) {
+
+		/* ctx MUST be allocated on the stack */
+		ptrdiff_t usedstack = ((char *)ctx - (char *)&ctx);
+		if(usedstack > 0) usedstack = -usedstack; /* grows up! */
+
+		/* double negative required to avoid int wrap-around */
+		if(usedstack < -(ptrdiff_t)ctx->max_stack_size) {
+			ASN_DEBUG("Stack limit %ld reached",
+				(long)ctx->max_stack_size);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* ASN_INTERNAL_H */
diff --git a/libkmod/pkcs7/asn1c-gen/asn_system.h b/libkmod/pkcs7/asn1c-gen/asn_system.h
new file mode 100644
index 000000000000..d19837edf59e
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/asn_system.h
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2003, 2004, 2007 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+/*
+ * Miscellaneous system-dependent types.
+ */
+#ifndef	ASN_SYSTEM_H
+#define	ASN_SYSTEM_H
+
+#ifdef	HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE /* for snprintf() on some linux systems  */
+#endif
+
+#include <stdio.h>	/* For snprintf(3) */
+#include <stdlib.h>	/* For *alloc(3) */
+#include <string.h>	/* For memcpy(3) */
+#include <sys/types.h>	/* For size_t */
+#include <limits.h>	/* For LONG_MAX */
+#include <stdarg.h>	/* For va_start */
+#include <stddef.h>	/* for offsetof and ptrdiff_t */
+
+#ifdef	HAVE_ALLOCA_H
+#include <alloca.h>	/* For alloca(3) */
+#endif
+
+#ifdef	_WIN32
+
+#include <malloc.h>
+#define	 snprintf	_snprintf
+#define	 vsnprintf	_vsnprintf
+
+/* To avoid linking with ws2_32.lib, here's the definition of ntohl() */
+#define sys_ntohl(l)	((((l) << 24)  & 0xff000000)	\
+			| (((l) << 8) & 0xff0000)	\
+			| (((l) >> 8)  & 0xff00)	\
+			| ((l >> 24) & 0xff))
+
+#ifdef _MSC_VER			/* MSVS.Net */
+#ifndef __cplusplus
+#define inline __inline
+#endif
+#ifndef	ASSUMESTDTYPES	/* Standard types have been defined elsewhere */
+#define	ssize_t		SSIZE_T
+typedef	char		int8_t;
+typedef	short		int16_t;
+typedef	int		int32_t;
+typedef	unsigned char	uint8_t;
+typedef	unsigned short	uint16_t;
+typedef	unsigned int	uint32_t;
+#endif	/* ASSUMESTDTYPES */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <float.h>
+#define isnan _isnan
+#define finite _finite
+#define copysign _copysign
+#define	ilogb	_logb
+#else	/* !_MSC_VER */
+#include <stdint.h>
+#endif	/* _MSC_VER */
+
+#else	/* !_WIN32 */
+
+#if defined(__vxworks)
+#include <types/vxTypes.h>
+#else	/* !defined(__vxworks) */
+
+#include <inttypes.h>	/* C99 specifies this file */
+/*
+ * 1. Earlier FreeBSD version didn't have <stdint.h>,
+ * but <inttypes.h> was present.
+ * 2. Sun Solaris requires <alloca.h> for alloca(3),
+ * but does not have <stdint.h>.
+ */
+#if	(!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_))
+#if	defined(sun)
+#include <alloca.h>	/* For alloca(3) */
+#include <ieeefp.h>	/* for finite(3) */
+#elif	defined(__hpux)
+#ifdef	__GNUC__
+#include <alloca.h>	/* For alloca(3) */
+#else	/* !__GNUC__ */
+#define inline
+#endif	/* __GNUC__ */
+#else
+#include <stdint.h>	/* SUSv2+ and C99 specify this file, for uintXX_t */
+#endif	/* defined(sun) */
+#endif
+
+#include <netinet/in.h> /* for ntohl() */
+#define	sys_ntohl(foo)	ntohl(foo)
+
+#endif	/* defined(__vxworks) */
+
+#endif	/* _WIN32 */
+
+#if	__GNUC__ >= 3
+#ifndef	GCC_PRINTFLIKE
+#define	GCC_PRINTFLIKE(fmt,var)	__attribute__((format(printf,fmt,var)))
+#endif
+#ifndef	GCC_NOTUSED
+#define	GCC_NOTUSED		__attribute__((unused))
+#endif
+#else
+#ifndef	GCC_PRINTFLIKE
+#define	GCC_PRINTFLIKE(fmt,var)	/* nothing */
+#endif
+#ifndef	GCC_NOTUSED
+#define	GCC_NOTUSED
+#endif
+#endif
+
+/* Figure out if thread safety is requested */
+#if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) || defined(_REENTRANT))
+#define	ASN_THREAD_SAFE
+#endif	/* Thread safety */
+
+#ifndef	offsetof	/* If not defined by <stddef.h> */
+#define	offsetof(s, m)	((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0))
+#endif	/* offsetof */
+
+#ifndef	MIN		/* Suitable for comparing primitive types (integers) */
+#if defined(__GNUC__)
+#define	MIN(a,b)	({ __typeof a _a = a; __typeof b _b = b;	\
+	((_a)<(_b)?(_a):(_b)); })
+#else	/* !__GNUC__ */
+#define	MIN(a,b)	((a)<(b)?(a):(b))	/* Unsafe variant */
+#endif /* __GNUC__ */
+#endif	/* MIN */
+
+#endif	/* ASN_SYSTEM_H */
diff --git a/libkmod/pkcs7/asn1c-gen/ber_decoder.c b/libkmod/pkcs7/asn1c-gen/ber_decoder.c
new file mode 100644
index 000000000000..b3a6329e063f
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ber_decoder.c
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+
+#undef	ADVANCE
+#define	ADVANCE(num_bytes)	do {					\
+		size_t num = num_bytes;					\
+		ptr = ((const char *)ptr) + num;			\
+		size -= num;						\
+		consumed_myself += num;					\
+	} while(0)
+#undef	RETURN
+#define	RETURN(_code)	do {						\
+		asn_dec_rval_t rval;					\
+		rval.code = _code;					\
+		if(opt_ctx) opt_ctx->step = step; /* Save context */	\
+		if(_code == RC_OK || opt_ctx)				\
+			rval.consumed = consumed_myself;		\
+		else							\
+			rval.consumed = 0;	/* Context-free */	\
+		return rval;						\
+	} while(0)
+
+/*
+ * The BER decoder of any type.
+ */
+asn_dec_rval_t
+ber_decode(asn_codec_ctx_t *opt_codec_ctx,
+	asn_TYPE_descriptor_t *type_descriptor,
+	void **struct_ptr, const void *ptr, size_t size) {
+	asn_codec_ctx_t s_codec_ctx;
+
+	/*
+	 * Stack checker requires that the codec context
+	 * must be allocated on the stack.
+	 */
+	if(opt_codec_ctx) {
+		if(opt_codec_ctx->max_stack_size) {
+			s_codec_ctx = *opt_codec_ctx;
+			opt_codec_ctx = &s_codec_ctx;
+		}
+	} else {
+		/* If context is not given, be security-conscious anyway */
+		memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
+		s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
+		opt_codec_ctx = &s_codec_ctx;
+	}
+
+	/*
+	 * Invoke type-specific decoder.
+	 */
+	return type_descriptor->ber_decoder(opt_codec_ctx, type_descriptor,
+		struct_ptr,	/* Pointer to the destination structure */
+		ptr, size,	/* Buffer and its size */
+		0		/* Default tag mode is 0 */
+		);
+}
+
+/*
+ * Check the set of <TL<TL<TL...>>> tags matches the definition.
+ */
+asn_dec_rval_t
+ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
+		asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx,
+		const void *ptr, size_t size, int tag_mode, int last_tag_form,
+		ber_tlv_len_t *last_length, int *opt_tlv_form) {
+	ssize_t consumed_myself = 0;
+	ssize_t tag_len;
+	ssize_t len_len;
+	ber_tlv_tag_t tlv_tag;
+	ber_tlv_len_t tlv_len;
+	ber_tlv_len_t limit_len = -1;
+	int expect_00_terminators = 0;
+	int tlv_constr = -1;	/* If CHOICE, opt_tlv_form is not given */
+	int step = opt_ctx ? opt_ctx->step : 0;	/* Where we left previously */
+	int tagno;
+
+	/*
+	 * Make sure we didn't exceed the maximum stack size.
+	 */
+	if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
+		RETURN(RC_FAIL);
+
+	/*
+	 * So what does all this implicit skip stuff mean?
+	 * Imagine two types,
+	 * 	A ::= [5] IMPLICIT	T
+	 * 	B ::= [2] EXPLICIT	T
+	 * Where T is defined as
+	 *	T ::= [4] IMPLICIT SEQUENCE { ... }
+	 * 
+	 * Let's say, we are starting to decode type A, given the
+	 * following TLV stream: <5> <0>. What does this mean?
+	 * It means that the type A contains type T which is,
+	 * in turn, empty.
+	 * Remember though, that we are still in A. We cannot
+	 * just pass control to the type T decoder. Why? Because
+	 * the type T decoder expects <4> <0>, not <5> <0>.
+	 * So, we must make sure we are going to receive <5> while
+	 * still in A, then pass control to the T decoder, indicating
+	 * that the tag <4> was implicitly skipped. The decoder of T
+	 * hence will be prepared to treat <4> as valid tag, and decode
+	 * it appropriately.
+	 */
+
+	tagno = step	/* Continuing where left previously */
+		+ (tag_mode==1?-1:0)
+		;
+	ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)",
+		td->name, (long)size, tag_mode, step, tagno);
+	/* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */
+
+	if(tag_mode == 0 && tagno == td->tags_count) {
+		/*
+		 * This must be the _untagged_ ANY type,
+		 * which outermost tag isn't known in advance.
+		 * Fetch the tag and length separately.
+		 */
+		tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
+		switch(tag_len) {
+		case -1: RETURN(RC_FAIL);
+		case 0: RETURN(RC_WMORE);
+		}
+		tlv_constr = BER_TLV_CONSTRUCTED(ptr);
+		len_len = ber_fetch_length(tlv_constr,
+			(const char *)ptr + tag_len, size - tag_len, &tlv_len);
+		switch(len_len) {
+		case -1: RETURN(RC_FAIL);
+		case 0: RETURN(RC_WMORE);
+		}
+		ASN_DEBUG("Advancing %ld in ANY case",
+			(long)(tag_len + len_len));
+		ADVANCE(tag_len + len_len);
+	} else {
+		assert(tagno < td->tags_count);	/* At least one loop */
+	}
+	for((void)tagno; tagno < td->tags_count; tagno++, step++) {
+
+		/*
+		 * Fetch and process T from TLV.
+		 */
+		tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
+			ASN_DEBUG("Fetching tag from {%p,%ld}: "
+				"len %ld, step %d, tagno %d got %s",
+				ptr, (long)size,
+				(long)tag_len, step, tagno,
+				ber_tlv_tag_string(tlv_tag));
+		switch(tag_len) {
+		case -1: RETURN(RC_FAIL);
+		case 0: RETURN(RC_WMORE);
+		}
+
+		tlv_constr = BER_TLV_CONSTRUCTED(ptr);
+
+		/*
+		 * If {I}, don't check anything.
+		 * If {I,B,C}, check B and C unless we're at I.
+		 */
+		if(tag_mode != 0 && step == 0) {
+			/*
+			 * We don't expect tag to match here.
+			 * It's just because we don't know how the tag
+			 * is supposed to look like.
+			 */
+		} else {
+		    assert(tagno >= 0);	/* Guaranteed by the code above */
+		    if(tlv_tag != td->tags[tagno]) {
+			/*
+			 * Unexpected tag. Too bad.
+			 */
+		    	ASN_DEBUG("Expected: %s, "
+				"expectation failed (tn=%d, tm=%d)",
+				ber_tlv_tag_string(td->tags[tagno]),
+				tagno, tag_mode
+			);
+			RETURN(RC_FAIL);
+		    }
+		}
+
+		/*
+		 * Attention: if there are more tags expected,
+		 * ensure that the current tag is presented
+		 * in constructed form (it contains other tags!).
+		 * If this one is the last one, check that the tag form
+		 * matches the one given in descriptor.
+		 */
+		if(tagno < (td->tags_count - 1)) {
+			if(tlv_constr == 0) {
+				ASN_DEBUG("tlv_constr = %d, expfail",
+					tlv_constr);
+				RETURN(RC_FAIL);
+			}
+		} else {
+			if(last_tag_form != tlv_constr
+			&& last_tag_form != -1) {
+				ASN_DEBUG("last_tag_form %d != %d",
+					last_tag_form, tlv_constr);
+				RETURN(RC_FAIL);
+			}
+		}
+
+		/*
+		 * Fetch and process L from TLV.
+		 */
+		len_len = ber_fetch_length(tlv_constr,
+			(const char *)ptr + tag_len, size - tag_len, &tlv_len);
+		ASN_DEBUG("Fetching len = %ld", (long)len_len);
+		switch(len_len) {
+		case -1: RETURN(RC_FAIL);
+		case 0: RETURN(RC_WMORE);
+		}
+
+		/*
+		 * FIXME
+		 * As of today, the chain of tags
+		 * must either contain several indefinite length TLVs,
+		 * or several definite length ones.
+		 * No mixing is allowed.
+		 */
+		if(tlv_len == -1) {
+			/*
+			 * Indefinite length.
+			 */
+			if(limit_len == -1) {
+				expect_00_terminators++;
+			} else {
+				ASN_DEBUG("Unexpected indefinite length "
+					"in a chain of definite lengths");
+				RETURN(RC_FAIL);
+			}
+			ADVANCE(tag_len + len_len);
+			continue;
+		} else {
+			if(expect_00_terminators) {
+				ASN_DEBUG("Unexpected definite length "
+					"in a chain of indefinite lengths");
+				RETURN(RC_FAIL);
+			}
+		}
+
+		/*
+		 * Check that multiple TLVs specify ever decreasing length,
+		 * which is consistent.
+		 */
+		if(limit_len == -1) {
+			limit_len    = tlv_len + tag_len + len_len;
+			if(limit_len < 0) {
+				/* Too great tlv_len value? */
+				RETURN(RC_FAIL);
+			}
+		} else if(limit_len != tlv_len + tag_len + len_len) {
+			/*
+			 * Inner TLV specifies length which is inconsistent
+			 * with the outer TLV's length value.
+			 */
+			ASN_DEBUG("Outer TLV is %ld and inner is %ld",
+				(long)limit_len, (long)tlv_len);
+			RETURN(RC_FAIL);
+		}
+
+		ADVANCE(tag_len + len_len);
+
+		limit_len -= (tag_len + len_len);
+		if((ssize_t)size > limit_len) {
+			/*
+			 * Make sure that we won't consume more bytes
+			 * from the parent frame than the inferred limit.
+			 */
+			size = limit_len;
+		}
+	}
+
+	if(opt_tlv_form)
+		*opt_tlv_form = tlv_constr;
+	if(expect_00_terminators)
+		*last_length = -expect_00_terminators;
+	else
+		*last_length = tlv_len;
+
+	RETURN(RC_OK);
+}
diff --git a/libkmod/pkcs7/asn1c-gen/ber_decoder.h b/libkmod/pkcs7/asn1c-gen/ber_decoder.h
new file mode 100644
index 000000000000..9fe2e895dfb6
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ber_decoder.h
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_BER_DECODER_H_
+#define	_BER_DECODER_H_
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;	/* Forward declaration */
+struct asn_codec_ctx_s;		/* Forward declaration */
+
+/*
+ * The BER decoder of any type.
+ * This function may be invoked directly from the application.
+ * The der_encode() function (der_encoder.h) is an opposite to ber_decode().
+ */
+asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx,
+	struct asn_TYPE_descriptor_s *type_descriptor,
+	void **struct_ptr,	/* Pointer to a target structure's pointer */
+	const void *buffer,	/* Data to be decoded */
+	size_t size		/* Size of that buffer */
+	);
+
+/*
+ * Type of generic function which decodes the byte stream into the structure.
+ */
+typedef asn_dec_rval_t (ber_type_decoder_f)(
+		struct asn_codec_ctx_s *opt_codec_ctx,
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		void **struct_ptr, const void *buf_ptr, size_t size,
+		int tag_mode);
+
+/*******************************
+ * INTERNALLY USEFUL FUNCTIONS *
+ *******************************/
+
+/*
+ * Check that all tags correspond to the type definition (as given in head).
+ * On return, last_length would contain either a non-negative length of the
+ * value part of the last TLV, or the negative number of expected
+ * "end of content" sequences. The number may only be negative if the
+ * head->last_tag_form is non-zero.
+ */
+asn_dec_rval_t ber_check_tags(
+		struct asn_codec_ctx_s *opt_codec_ctx,	/* codec options */
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		asn_struct_ctx_t *opt_ctx,	/* saved decoding context */
+		const void *ptr, size_t size,
+		int tag_mode,		/* {-1,0,1}: IMPLICIT, no, EXPLICIT */
+		int last_tag_form,	/* {-1,0:1}: any, primitive, constr */
+		ber_tlv_len_t *last_length,
+		int *opt_tlv_form	/* optional tag form */
+	);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _BER_DECODER_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/ber_tlv_length.c b/libkmod/pkcs7/asn1c-gen/ber_tlv_length.c
new file mode 100644
index 000000000000..4c2f1e5fd3cc
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ber_tlv_length.c
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <ber_tlv_length.h>
+#include <ber_tlv_tag.h>
+
+ssize_t
+ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,
+		ber_tlv_len_t *len_r) {
+	const uint8_t *buf = (const uint8_t *)bufptr;
+	unsigned oct;
+
+	if(size == 0)
+		return 0;	/* Want more */
+
+	oct = *(const uint8_t *)buf;
+	if((oct & 0x80) == 0) {
+		/*
+		 * Short definite length.
+		 */
+		*len_r = oct;	/* & 0x7F */
+		return 1;
+	} else {
+		ber_tlv_len_t len;
+		size_t skipped;
+
+		if(_is_constructed && oct == 0x80) {
+			*len_r = -1;	/* Indefinite length */
+			return 1;
+		}
+
+		if(oct == 0xff) {
+			/* Reserved in standard for future use. */
+			return -1;
+		}
+
+		oct &= 0x7F;	/* Leave only the 7 LS bits */
+		for(len = 0, buf++, skipped = 1;
+			oct && (++skipped <= size); buf++, oct--) {
+
+			len = (len << 8) | *buf;
+			if(len < 0
+			|| (len >> ((8 * sizeof(len)) - 8) && oct > 1)) {
+				/*
+				 * Too large length value.
+				 */
+				return -1;
+			}
+		}
+
+		if(oct == 0) {
+			ber_tlv_len_t lenplusepsilon = (size_t)len + 1024;
+			/*
+			 * Here length may be very close or equal to 2G.
+			 * However, the arithmetics used in some decoders
+			 * may add some (small) quantities to the length,
+			 * to check the resulting value against some limits.
+			 * This may result in integer wrap-around, which
+			 * we try to avoid by checking it earlier here.
+			 */
+			if(lenplusepsilon < 0) {
+				/* Too large length value */
+				return -1;
+			}
+
+			*len_r = len;
+			return skipped;
+		}
+
+		return 0;	/* Want more */
+	}
+
+}
+
+ssize_t
+ber_skip_length(asn_codec_ctx_t *opt_codec_ctx,
+		int _is_constructed, const void *ptr, size_t size) {
+	ber_tlv_len_t vlen;	/* Length of V in TLV */
+	ssize_t tl;		/* Length of L in TLV */
+	ssize_t ll;		/* Length of L in TLV */
+	size_t skip;
+
+	/*
+	 * Make sure we didn't exceed the maximum stack size.
+	 */
+	if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
+		return -1;
+
+	/*
+	 * Determine the size of L in TLV.
+	 */
+	ll = ber_fetch_length(_is_constructed, ptr, size, &vlen);
+	if(ll <= 0) return ll;
+
+	/*
+	 * Definite length.
+	 */
+	if(vlen >= 0) {
+		skip = ll + vlen;
+		if(skip > size)
+			return 0;	/* Want more */
+		return skip;
+	}
+
+	/*
+	 * Indefinite length!
+	 */
+	ASN_DEBUG("Skipping indefinite length");
+	for(skip = ll, ptr = ((const char *)ptr) + ll, size -= ll;;) {
+		ber_tlv_tag_t tag;
+
+		/* Fetch the tag */
+		tl = ber_fetch_tag(ptr, size, &tag);
+		if(tl <= 0) return tl;
+
+		ll = ber_skip_length(opt_codec_ctx,
+			BER_TLV_CONSTRUCTED(ptr),
+			((const char *)ptr) + tl, size - tl);
+		if(ll <= 0) return ll;
+
+		skip += tl + ll;
+
+		/*
+		 * This may be the end of the indefinite length structure,
+		 * two consecutive 0 octets.
+		 * Check if it is true.
+		 */
+		if(((const uint8_t *)ptr)[0] == 0
+		&& ((const uint8_t *)ptr)[1] == 0)
+			return skip;
+
+		ptr = ((const char *)ptr) + tl + ll;
+		size -= tl + ll;
+ 	}
+
+	/* UNREACHABLE */
+}
+
+size_t
+der_tlv_length_serialize(ber_tlv_len_t len, void *bufp, size_t size) {
+	size_t required_size;	/* Size of len encoding */
+	uint8_t *buf = (uint8_t *)bufp;
+	uint8_t *end;
+	size_t i;
+
+	if(len <= 127) {
+		/* Encoded in 1 octet */
+		if(size) *buf = (uint8_t)len;
+		return 1;
+	}
+
+	/*
+	 * Compute the size of the subsequent bytes.
+	 */
+	for(required_size = 1, i = 8; i < 8 * sizeof(len); i += 8) {
+		if(len >> i)
+			required_size++;
+		else
+			break;
+	}
+
+	if(size <= required_size)
+		return required_size + 1;
+
+	*buf++ = (uint8_t)(0x80 | required_size);  /* Length of the encoding */
+
+	/*
+	 * Produce the len encoding, space permitting.
+	 */
+	end = buf + required_size;
+	for(i -= 8; buf < end; i -= 8, buf++)
+		*buf = (uint8_t)(len >> i);
+
+	return required_size + 1;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/ber_tlv_length.h b/libkmod/pkcs7/asn1c-gen/ber_tlv_length.h
new file mode 100644
index 000000000000..349680224401
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ber_tlv_length.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_BER_TLV_LENGTH_H_
+#define	_BER_TLV_LENGTH_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef ssize_t ber_tlv_len_t;
+
+/*
+ * This function tries to fetch the length of the BER TLV value and place it
+ * in *len_r.
+ * RETURN VALUES:
+ *	 0:	More data expected than bufptr contains.
+ *	-1:	Fatal error deciphering length.
+ *	>0:	Number of bytes used from bufptr.
+ * On return with >0, len_r is constrained as -1..MAX, where -1 mean
+ * that the value is of indefinite length.
+ */
+ssize_t ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,
+	ber_tlv_len_t *len_r);
+
+/*
+ * This function expects bufptr to be positioned over L in TLV.
+ * It returns number of bytes occupied by L and V together, suitable
+ * for skipping. The function properly handles indefinite length.
+ * RETURN VALUES:
+ * 	Standard {-1,0,>0} convention.
+ */
+ssize_t ber_skip_length(
+	struct asn_codec_ctx_s *opt_codec_ctx,	/* optional context */
+	int _is_constructed, const void *bufptr, size_t size);
+
+/*
+ * This function serializes the length (L from TLV) in DER format.
+ * It always returns number of bytes necessary to represent the length,
+ * it is a caller's responsibility to check the return value
+ * against the supplied buffer's size.
+ */
+size_t der_tlv_length_serialize(ber_tlv_len_t len, void *bufptr, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _BER_TLV_LENGTH_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c b/libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c
new file mode 100644
index 000000000000..42708760e089
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <ber_tlv_tag.h>
+#include <errno.h>
+
+ssize_t
+ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) {
+	ber_tlv_tag_t val;
+	ber_tlv_tag_t tclass;
+	size_t skipped;
+
+	if(size == 0)
+		return 0;
+
+	val = *(const uint8_t *)ptr;
+	tclass = (val >> 6);
+	if((val &= 0x1F) != 0x1F) {
+		/*
+		 * Simple form: everything encoded in a single octet.
+		 * Tag Class is encoded using two least significant bits.
+		 */
+		*tag_r = (val << 2) | tclass;
+		return 1;
+	}
+
+	/*
+	 * Each octet contains 7 bits of useful information.
+	 * The MSB is 0 if it is the last octet of the tag.
+	 */
+	for(val = 0, ptr = ((const char *)ptr) + 1, skipped = 2;
+			skipped <= size;
+				ptr = ((const char *)ptr) + 1, skipped++) {
+		unsigned int oct = *(const uint8_t *)ptr;
+		if(oct & 0x80) {
+			val = (val << 7) | (oct & 0x7F);
+			/*
+			 * Make sure there are at least 9 bits spare
+			 * at the MS side of a value.
+			 */
+			if(val >> ((8 * sizeof(val)) - 9)) {
+				/*
+				 * We would not be able to accomodate
+				 * any more tag bits.
+				 */
+				return -1;
+			}
+		} else {
+			val = (val << 7) | oct;
+			*tag_r = (val << 2) | tclass;
+			return skipped;
+		}
+	}
+
+	return 0;	/* Want more */
+}
+
+
+ssize_t
+ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) {
+	char buf[sizeof("[APPLICATION ]") + 32];
+	ssize_t ret;
+
+	ret = ber_tlv_tag_snprint(tag, buf, sizeof(buf));
+	if(ret >= (ssize_t)sizeof(buf) || ret < 2) {
+		errno = EPERM;
+		return -1;
+	}
+
+	return fwrite(buf, 1, ret, f);
+}
+
+ssize_t
+ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) {
+	char *type = 0;
+	int ret;
+
+	switch(tag & 0x3) {
+	case ASN_TAG_CLASS_UNIVERSAL:	type = "UNIVERSAL ";	break;
+	case ASN_TAG_CLASS_APPLICATION:	type = "APPLICATION ";	break;
+	case ASN_TAG_CLASS_CONTEXT:	type = "";		break;
+	case ASN_TAG_CLASS_PRIVATE:	type = "PRIVATE ";	break;
+	}
+
+	ret = snprintf(buf, size, "[%s%u]", type, ((unsigned)tag) >> 2);
+	if(ret <= 0 && size) buf[0] = '\0';	/* against broken libc's */
+
+	return ret;
+}
+
+char *
+ber_tlv_tag_string(ber_tlv_tag_t tag) {
+	static char buf[sizeof("[APPLICATION ]") + 32];
+
+	(void)ber_tlv_tag_snprint(tag, buf, sizeof(buf));
+
+	return buf;
+}
+
+
+size_t
+ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufp, size_t size) {
+	int tclass = BER_TAG_CLASS(tag);
+	ber_tlv_tag_t tval = BER_TAG_VALUE(tag);
+	uint8_t *buf = (uint8_t *)bufp;
+	uint8_t *end;
+	size_t required_size;
+	size_t i;
+
+	if(tval <= 30) {
+		/* Encoded in 1 octet */
+		if(size) buf[0] = (tclass << 6) | tval;
+		return 1;
+	} else if(size) {
+		*buf++ = (tclass << 6) | 0x1F;
+		size--;
+	}
+
+	/*
+	 * Compute the size of the subsequent bytes.
+	 */
+	for(required_size = 1, i = 7; i < 8 * sizeof(tval); i += 7) {
+		if(tval >> i)
+			required_size++;
+		else
+			break;
+	}
+
+	if(size < required_size)
+		return required_size + 1;
+
+	/*
+	 * Fill in the buffer, space permitting.
+	 */
+	end = buf + required_size - 1;
+	for(i -= 7; buf < end; i -= 7, buf++)
+		*buf = 0x80 | ((tval >> i) & 0x7F);
+	*buf = (tval & 0x7F);	/* Last octet without high bit */
+
+	return required_size + 1;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h b/libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h
new file mode 100644
index 000000000000..60e866861b28
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_BER_TLV_TAG_H_
+#define	_BER_TLV_TAG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum asn_tag_class {
+	ASN_TAG_CLASS_UNIVERSAL		= 0,	/* 0b00 */
+	ASN_TAG_CLASS_APPLICATION	= 1,	/* 0b01 */
+	ASN_TAG_CLASS_CONTEXT		= 2,	/* 0b10 */
+	ASN_TAG_CLASS_PRIVATE		= 3	/* 0b11 */
+};
+typedef unsigned ber_tlv_tag_t;	/* BER TAG from Tag-Length-Value */
+
+/*
+ * Tag class is encoded together with tag value for optimization purposes.
+ */
+#define	BER_TAG_CLASS(tag)	((tag) & 0x3)
+#define	BER_TAG_VALUE(tag)	((tag) >> 2)
+#define	BER_TLV_CONSTRUCTED(tagptr)	(((*(const uint8_t *)tagptr)&0x20)?1:0)
+
+#define	BER_TAGS_EQUAL(tag1, tag2)	((tag1) == (tag2))
+
+/*
+ * Several functions for printing the TAG in the canonical form
+ * (i.e. "[PRIVATE 0]").
+ * Return values correspond to their libc counterparts (if any).
+ */
+ssize_t ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t buflen);
+ssize_t ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *);
+char *ber_tlv_tag_string(ber_tlv_tag_t tag);
+
+
+/*
+ * This function tries to fetch the tag from the input stream.
+ * RETURN VALUES:
+ * 	 0:	More data expected than bufptr contains.
+ * 	-1:	Fatal error deciphering tag.
+ *	>0:	Number of bytes used from bufptr. tag_r will contain the tag.
+ */
+ssize_t ber_fetch_tag(const void *bufptr, size_t size, ber_tlv_tag_t *tag_r);
+
+/*
+ * This function serializes the tag (T from TLV) in BER format.
+ * It always returns number of bytes necessary to represent the tag,
+ * it is a caller's responsibility to check the return value
+ * against the supplied buffer's size.
+ */
+size_t ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufptr, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _BER_TLV_TAG_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/constr_CHOICE.c b/libkmod/pkcs7/asn1c-gen/constr_CHOICE.c
new file mode 100644
index 000000000000..6116e6a6b0b4
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_CHOICE.c
@@ -0,0 +1,1114 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_CHOICE.h>
+#include <per_opentype.h>
+
+/*
+ * Number of bytes left for this structure.
+ * (ctx->left) indicates the number of bytes _transferred_ for the structure.
+ * (size) contains the number of bytes in the buffer passed.
+ */
+#define	LEFT	((size<(size_t)ctx->left)?size:(size_t)ctx->left)
+
+/*
+ * If the subprocessor function returns with an indication that it wants
+ * more data, it may well be a fatal decoding problem, because the
+ * size is constrained by the <TLV>'s L, even if the buffer size allows
+ * reading more data.
+ * For example, consider the buffer containing the following TLVs:
+ * <T:5><L:1><V> <T:6>...
+ * The TLV length clearly indicates that one byte is expected in V, but
+ * if the V processor returns with "want more data" even if the buffer
+ * contains way more data than the V processor have seen.
+ */
+#define	SIZE_VIOLATION	(ctx->left >= 0 && (size_t)ctx->left <= size)
+
+/*
+ * This macro "eats" the part of the buffer which is definitely "consumed",
+ * i.e. was correctly converted into local representation or rightfully skipped.
+ */
+#undef	ADVANCE
+#define	ADVANCE(num_bytes)	do {		\
+		size_t num = num_bytes;		\
+		ptr = ((const char *)ptr) + num;\
+		size -= num;			\
+		if(ctx->left >= 0)		\
+			ctx->left -= num;	\
+		consumed_myself += num;		\
+	} while(0)
+
+/*
+ * Switch to the next phase of parsing.
+ */
+#undef	NEXT_PHASE
+#define	NEXT_PHASE(ctx)	do {			\
+		ctx->phase++;			\
+		ctx->step = 0;			\
+	} while(0)
+
+/*
+ * Return a standardized complex structure.
+ */
+#undef	RETURN
+#define	RETURN(_code)	do {			\
+		rval.code = _code;		\
+		rval.consumed = consumed_myself;\
+		return rval;			\
+	} while(0)
+
+/*
+ * See the definitions.
+ */
+static int _fetch_present_idx(const void *struct_ptr, int off, int size);
+static void _set_present_idx(void *sptr, int offset, int size, int pres);
+
+/*
+ * Tags are canonically sorted in the tag to member table.
+ */
+static int
+_search4tag(const void *ap, const void *bp) {
+	const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
+	const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
+
+	int a_class = BER_TAG_CLASS(a->el_tag);
+	int b_class = BER_TAG_CLASS(b->el_tag);
+
+	if(a_class == b_class) {
+		ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
+		ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
+
+		if(a_value == b_value)
+			return 0;
+		else if(a_value < b_value)
+			return -1;
+		else
+			return 1;
+	} else if(a_class < b_class) {
+		return -1;
+	} else {
+		return 1;
+	}
+}
+
+/*
+ * The decoder of the CHOICE type.
+ */
+asn_dec_rval_t
+CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+	void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
+	/*
+	 * Bring closer parts of structure description.
+	 */
+	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+	asn_TYPE_member_t *elements = td->elements;
+
+	/*
+	 * Parts of the structure being constructed.
+	 */
+	void *st = *struct_ptr;	/* Target structure. */
+	asn_struct_ctx_t *ctx;	/* Decoder context */
+
+	ber_tlv_tag_t tlv_tag;	/* T from TLV */
+	ssize_t tag_len;	/* Length of TLV's T */
+	asn_dec_rval_t rval;	/* Return code from subparsers */
+
+	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
+
+	ASN_DEBUG("Decoding %s as CHOICE", td->name);
+
+	/*
+	 * Create the target structure if it is not present already.
+	 */
+	if(st == 0) {
+		st = *struct_ptr = CALLOC(1, specs->struct_size);
+		if(st == 0) {
+			RETURN(RC_FAIL);
+		}
+	}
+
+	/*
+	 * Restore parsing context.
+	 */
+	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
+	
+	/*
+	 * Start to parse where left previously
+	 */
+	switch(ctx->phase) {
+	case 0:
+		/*
+		 * PHASE 0.
+		 * Check that the set of tags associated with given structure
+		 * perfectly fits our expectations.
+		 */
+
+		if(tag_mode || td->tags_count) {
+			rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
+				tag_mode, -1, &ctx->left, 0);
+			if(rval.code != RC_OK) {
+				ASN_DEBUG("%s tagging check failed: %d",
+					td->name, rval.code);
+				return rval;
+			}
+
+			if(ctx->left >= 0) {
+				/* ?Substracted below! */
+				ctx->left += rval.consumed;
+			}
+			ADVANCE(rval.consumed);
+		} else {
+			ctx->left = -1;
+		}
+
+		NEXT_PHASE(ctx);
+
+		ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
+			(long)ctx->left, (long)size);
+
+		/* Fall through */
+	case 1:
+		/*
+		 * Fetch the T from TLV.
+		 */
+		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
+		ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len);
+		switch(tag_len) {
+		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
+			/* Fall through */
+		case -1: RETURN(RC_FAIL);
+		}
+
+		do {
+			const asn_TYPE_tag2member_t *t2m;
+			asn_TYPE_tag2member_t key;
+
+			key.el_tag = tlv_tag;
+			t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
+					specs->tag2el, specs->tag2el_count,
+					sizeof(specs->tag2el[0]), _search4tag);
+			if(t2m) {
+				/*
+				 * Found the element corresponding to the tag.
+				 */
+				NEXT_PHASE(ctx);
+				ctx->step = t2m->el_no;
+				break;
+			} else if(specs->ext_start == -1) {
+				ASN_DEBUG("Unexpected tag %s "
+					"in non-extensible CHOICE %s",
+					ber_tlv_tag_string(tlv_tag), td->name);
+				RETURN(RC_FAIL);
+			} else {
+				/* Skip this tag */
+				ssize_t skip;
+
+				ASN_DEBUG("Skipping unknown tag %s",
+					ber_tlv_tag_string(tlv_tag));
+
+				skip = ber_skip_length(opt_codec_ctx,
+					BER_TLV_CONSTRUCTED(ptr),
+					(const char *)ptr + tag_len,
+					LEFT - tag_len);
+
+				switch(skip) {
+				case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
+					/* Fall through */
+				case -1: RETURN(RC_FAIL);
+				}
+
+				ADVANCE(skip + tag_len);
+				RETURN(RC_OK);
+			}
+		} while(0);
+
+	case 2:
+		/*
+		 * PHASE 2.
+		 * Read in the element.
+		 */
+	    do {
+		asn_TYPE_member_t *elm;/* CHOICE's element */
+		void *memb_ptr;		/* Pointer to the member */
+		void **memb_ptr2;	/* Pointer to that pointer */
+
+		elm = &elements[ctx->step];
+
+		/*
+		 * Compute the position of the member inside a structure,
+		 * and also a type of containment (it may be contained
+		 * as pointer or using inline inclusion).
+		 */
+		if(elm->flags & ATF_POINTER) {
+			/* Member is a pointer to another structure */
+			memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+		} else {
+			/*
+			 * A pointer to a pointer
+			 * holding the start of the structure
+			 */
+			memb_ptr = (char *)st + elm->memb_offset;
+			memb_ptr2 = &memb_ptr;
+		}
+		/* Set presence to be able to free it properly at any time */
+		_set_present_idx(st, specs->pres_offset,
+				specs->pres_size, ctx->step + 1);
+		/*
+		 * Invoke the member fetch routine according to member's type
+		 */
+		rval = elm->type->ber_decoder(opt_codec_ctx, elm->type,
+				memb_ptr2, ptr, LEFT, elm->tag_mode);
+		switch(rval.code) {
+		case RC_OK:
+			break;
+		case RC_WMORE: /* More data expected */
+			if(!SIZE_VIOLATION) {
+				ADVANCE(rval.consumed);
+				RETURN(RC_WMORE);
+			}
+			RETURN(RC_FAIL);
+		case RC_FAIL: /* Fatal error */
+			RETURN(rval.code);
+		} /* switch(rval) */
+		
+		ADVANCE(rval.consumed);
+	  } while(0);
+
+		NEXT_PHASE(ctx);
+
+		/* Fall through */
+	case 3:
+		ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d",
+			td->name, (long)ctx->left, (long)size,
+			tag_mode, td->tags_count);
+
+		if(ctx->left > 0) {
+			/*
+			 * The type must be fully decoded
+			 * by the CHOICE member-specific decoder.
+			 */
+			RETURN(RC_FAIL);
+		}
+
+		if(ctx->left == -1
+		&& !(tag_mode || td->tags_count)) {
+			/*
+			 * This is an untagged CHOICE.
+			 * It doesn't contain nothing
+			 * except for the member itself, including all its tags.
+			 * The decoding is completed.
+			 */
+			NEXT_PHASE(ctx);
+			break;
+		}
+
+		/*
+		 * Read in the "end of data chunks"'s.
+		 */
+		while(ctx->left < 0) {
+			ssize_t tl;
+
+			tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
+			switch(tl) {
+			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
+				/* Fall through */
+			case -1: RETURN(RC_FAIL);
+			}
+
+			/*
+			 * Expected <0><0>...
+			 */
+			if(((const uint8_t *)ptr)[0] == 0) {
+				if(LEFT < 2) {
+					if(SIZE_VIOLATION)
+						RETURN(RC_FAIL);
+					else
+						RETURN(RC_WMORE);
+				} else if(((const uint8_t *)ptr)[1] == 0) {
+					/*
+					 * Correctly finished with <0><0>.
+					 */
+					ADVANCE(2);
+					ctx->left++;
+					continue;
+				}
+			} else {
+				ASN_DEBUG("Unexpected continuation in %s",
+					td->name);
+				RETURN(RC_FAIL);
+			}
+
+			/* UNREACHABLE */
+		}
+
+		NEXT_PHASE(ctx);
+	case 4:
+		/* No meaningful work here */
+		break;
+	}
+	
+	RETURN(RC_OK);
+}
+
+asn_enc_rval_t
+CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
+		int tag_mode, ber_tlv_tag_t tag,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+	asn_TYPE_member_t *elm;	/* CHOICE element */
+	asn_enc_rval_t erval;
+	void *memb_ptr;
+	size_t computed_size = 0;
+	int present;
+
+	if(!sptr) ASN__ENCODE_FAILED;
+
+	ASN_DEBUG("%s %s as CHOICE",
+		cb?"Encoding":"Estimating", td->name);
+
+	present = _fetch_present_idx(sptr,
+		specs->pres_offset, specs->pres_size);
+
+	/*
+	 * If the structure was not initialized, it cannot be encoded:
+	 * can't deduce what to encode in the choice type.
+	 */
+	if(present <= 0 || present > td->elements_count) {
+		if(present == 0 && td->elements_count == 0) {
+			/* The CHOICE is empty?! */
+			erval.encoded = 0;
+			ASN__ENCODED_OK(erval);
+		}
+		ASN__ENCODE_FAILED;
+	}
+
+	/*
+	 * Seek over the present member of the structure.
+	 */
+	elm = &td->elements[present-1];
+	if(elm->flags & ATF_POINTER) {
+		memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+		if(memb_ptr == 0) {
+			if(elm->optional) {
+				erval.encoded = 0;
+				ASN__ENCODED_OK(erval);
+			}
+			/* Mandatory element absent */
+			ASN__ENCODE_FAILED;
+		}
+	} else {
+		memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+	}
+
+	/*
+	 * If the CHOICE itself is tagged EXPLICIT:
+	 * T ::= [2] EXPLICIT CHOICE { ... }
+	 * Then emit the appropriate tags.
+	 */
+	if(tag_mode == 1 || td->tags_count) {
+		/*
+		 * For this, we need to pre-compute the member.
+		 */
+		ssize_t ret;
+
+		/* Encode member with its tag */
+		erval = elm->type->der_encoder(elm->type, memb_ptr,
+			elm->tag_mode, elm->tag, 0, 0);
+		if(erval.encoded == -1)
+			return erval;
+
+		/* Encode CHOICE with parent or my own tag */
+		ret = der_write_tags(td, erval.encoded, tag_mode, 1, tag,
+			cb, app_key);
+		if(ret == -1)
+			ASN__ENCODE_FAILED;
+		computed_size += ret;
+	}
+
+	/*
+	 * Encode the single underlying member.
+	 */
+	erval = elm->type->der_encoder(elm->type, memb_ptr,
+		elm->tag_mode, elm->tag, cb, app_key);
+	if(erval.encoded == -1)
+		return erval;
+
+	ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)",
+		(long)erval.encoded, (long)computed_size);
+
+	erval.encoded += computed_size;
+
+	return erval;
+}
+
+ber_tlv_tag_t
+CHOICE_outmost_tag(const asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) {
+	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+	int present;
+
+	assert(tag_mode == 0); (void)tag_mode;
+	assert(tag == 0); (void)tag;
+
+	/*
+	 * Figure out which CHOICE element is encoded.
+	 */
+	present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
+
+	if(present > 0 || present <= td->elements_count) {
+		const asn_TYPE_member_t *elm = &td->elements[present-1];
+		const void *memb_ptr;
+
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(const void * const *)
+					((const char *)ptr + elm->memb_offset);
+		} else {
+			memb_ptr = (const void *)
+					((const char *)ptr + elm->memb_offset);
+		}
+
+		return asn_TYPE_outmost_tag(elm->type, memb_ptr,
+			elm->tag_mode, elm->tag);
+	} else {
+		return (ber_tlv_tag_t)-1;
+	}
+}
+
+int
+CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+	int present;
+
+	if(!sptr) {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: value not given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Figure out which CHOICE element is encoded.
+	 */
+	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
+	if(present > 0 && present <= td->elements_count) {
+		asn_TYPE_member_t *elm = &td->elements[present-1];
+		const void *memb_ptr;
+
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
+			if(!memb_ptr) {
+				if(elm->optional)
+					return 0;
+				ASN__CTFAIL(app_key, td, sptr,
+					"%s: mandatory CHOICE element %s absent (%s:%d)",
+					td->name, elm->name, __FILE__, __LINE__);
+				return -1;
+			}
+		} else {
+			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
+		}
+
+		if(elm->memb_constraints) {
+			return elm->memb_constraints(elm->type, memb_ptr,
+				ctfailcb, app_key);
+		} else {
+			int ret = elm->type->check_constraints(elm->type,
+					memb_ptr, ctfailcb, app_key);
+			/*
+			 * Cannot inherit it eralier:
+			 * need to make sure we get the updated version.
+			 */
+			elm->memb_constraints = elm->type->check_constraints;
+			return ret;
+		}
+	} else {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: no CHOICE element given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+}
+
+#undef	XER_ADVANCE
+#define	XER_ADVANCE(num_bytes)	do {			\
+		size_t num = num_bytes;			\
+		buf_ptr = (const void *)(((const char *)buf_ptr) + num); \
+		size -= num;				\
+		consumed_myself += num;			\
+	} while(0)
+
+/*
+ * Decode the XER (XML) data.
+ */
+asn_dec_rval_t
+CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+	void **struct_ptr, const char *opt_mname,
+		const void *buf_ptr, size_t size) {
+	/*
+	 * Bring closer parts of structure description.
+	 */
+	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
+
+	/*
+	 * Parts of the structure being constructed.
+	 */
+	void *st = *struct_ptr;	/* Target structure. */
+	asn_struct_ctx_t *ctx;	/* Decoder context */
+
+	asn_dec_rval_t rval;		/* Return value of a decoder */
+	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
+	int edx;			/* Element index */
+
+	/*
+	 * Create the target structure if it is not present already.
+	 */
+	if(st == 0) {
+		st = *struct_ptr = CALLOC(1, specs->struct_size);
+		if(st == 0) RETURN(RC_FAIL);
+	}
+
+	/*
+	 * Restore parsing context.
+	 */
+	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
+	if(ctx->phase == 0 && !*xml_tag)
+		ctx->phase = 1;	/* Skip the outer tag checking phase */
+
+	/*
+	 * Phases of XER/XML processing:
+	 * Phase 0: Check that the opening tag matches our expectations.
+	 * Phase 1: Processing body and reacting on closing tag.
+	 * Phase 2: Processing inner type.
+	 * Phase 3: Only waiting for closing tag.
+	 * Phase 4: Skipping unknown extensions.
+	 * Phase 5: PHASED OUT
+	 */
+	for(edx = ctx->step; ctx->phase <= 4;) {
+		pxer_chunk_type_e ch_type;	/* XER chunk type */
+		ssize_t ch_size;		/* Chunk size */
+		xer_check_tag_e tcv;		/* Tag check value */
+		asn_TYPE_member_t *elm;
+
+		/*
+		 * Go inside the member.
+		 */
+		if(ctx->phase == 2) {
+			asn_dec_rval_t tmprval;
+			void *memb_ptr;		/* Pointer to the member */
+			void **memb_ptr2;	/* Pointer to that pointer */
+
+			elm = &td->elements[edx];
+
+			if(elm->flags & ATF_POINTER) {
+				/* Member is a pointer to another structure */
+				memb_ptr2 = (void **)((char *)st
+					+ elm->memb_offset);
+			} else {
+				memb_ptr = (char *)st + elm->memb_offset;
+				memb_ptr2 = &memb_ptr;
+			}
+
+			/* Start/Continue decoding the inner member */
+			tmprval = elm->type->xer_decoder(opt_codec_ctx,
+					elm->type, memb_ptr2, elm->name,
+					buf_ptr, size);
+			XER_ADVANCE(tmprval.consumed);
+			ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d",
+				elm->type->name, tmprval.code);
+			if(tmprval.code != RC_OK)
+				RETURN(tmprval.code);
+			assert(_fetch_present_idx(st,
+				specs->pres_offset, specs->pres_size) == 0);
+			/* Record what we've got */
+			_set_present_idx(st,
+				specs->pres_offset, specs->pres_size, edx + 1);
+			ctx->phase = 3;
+			/* Fall through */
+		}
+
+		/* No need to wait for closing tag; special mode. */
+		if(ctx->phase == 3 && !*xml_tag) {
+			ctx->phase = 5;	/* Phase out */
+			RETURN(RC_OK);
+		}
+
+		/*
+		 * Get the next part of the XML stream.
+		 */
+		ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type);
+		if(ch_size == -1) {
+            RETURN(RC_FAIL);
+        } else {
+			switch(ch_type) {
+			case PXER_WMORE:
+                RETURN(RC_WMORE);
+			case PXER_COMMENT:	/* Got XML comment */
+			case PXER_TEXT:		/* Ignore free-standing text */
+				XER_ADVANCE(ch_size);	/* Skip silently */
+				continue;
+			case PXER_TAG:
+				break;	/* Check the rest down there */
+			}
+		}
+
+		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
+		ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d",
+			ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
+			ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
+			ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
+			ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
+		xml_tag, tcv);
+
+		/* Skip the extensions section */
+		if(ctx->phase == 4) {
+			ASN_DEBUG("skip_unknown(%d, %ld)",
+				tcv, (long)ctx->left);
+			switch(xer_skip_unknown(tcv, &ctx->left)) {
+			case -1:
+				ctx->phase = 5;
+				RETURN(RC_FAIL);
+				continue;
+			case 1:
+				ctx->phase = 3;
+				/* Fall through */
+			case 0:
+				XER_ADVANCE(ch_size);
+				continue;
+			case 2:
+				ctx->phase = 3;
+				break;
+			}
+		}
+
+		switch(tcv) {
+		case XCT_BOTH:
+			break;	/* No CHOICE? */
+		case XCT_CLOSING:
+			if(ctx->phase != 3)
+				break;
+			XER_ADVANCE(ch_size);
+			ctx->phase = 5;	/* Phase out */
+			RETURN(RC_OK);
+		case XCT_OPENING:
+			if(ctx->phase == 0) {
+				XER_ADVANCE(ch_size);
+				ctx->phase = 1;	/* Processing body phase */
+				continue;
+			}
+			/* Fall through */
+		case XCT_UNKNOWN_OP:
+		case XCT_UNKNOWN_BO:
+
+			if(ctx->phase != 1)
+				break;	/* Really unexpected */
+
+			/*
+			 * Search which inner member corresponds to this tag.
+			 */
+			for(edx = 0; edx < td->elements_count; edx++) {
+				elm = &td->elements[edx];
+				tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
+				switch(tcv) {
+				case XCT_BOTH:
+				case XCT_OPENING:
+					/*
+					 * Process this member.
+					 */
+					ctx->step = edx;
+					ctx->phase = 2;
+					break;
+				case XCT_UNKNOWN_OP:
+				case XCT_UNKNOWN_BO:
+					continue;
+				default:
+					edx = td->elements_count;
+					break;	/* Phase out */
+				}
+				break;
+			}
+			if(edx != td->elements_count)
+				continue;
+
+			/* It is expected extension */
+			if(specs->ext_start != -1) {
+				ASN_DEBUG("Got anticipated extension");
+				/*
+				 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
+				 * By using a mask. Only record a pure
+				 * <opening> tags.
+				 */
+				if(tcv & XCT_CLOSING) {
+					/* Found </extension> without body */
+					ctx->phase = 3; /* Terminating */
+				} else {
+					ctx->left = 1;
+					ctx->phase = 4; /* Skip ...'s */
+				}
+				XER_ADVANCE(ch_size);
+				continue;
+			}
+
+			/* Fall through */
+		default:
+			break;
+		}
+
+		ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]"
+			" (ph=%d, tag=%s)",
+			ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
+			ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
+			ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
+			ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
+			td->name, ctx->phase, xml_tag);
+		break;
+	}
+
+	ctx->phase = 5;	/* Phase out, just in case */
+	RETURN(RC_FAIL);
+}
+
+
+asn_enc_rval_t
+CHOICE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_CHOICE_specifics_t *specs=(asn_CHOICE_specifics_t *)td->specifics;
+	asn_enc_rval_t er;
+	int present;
+
+	if(!sptr)
+		ASN__ENCODE_FAILED;
+
+	/*
+	 * Figure out which CHOICE element is encoded.
+	 */
+	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
+
+	if(present <= 0 || present > td->elements_count) {
+		ASN__ENCODE_FAILED;
+	}  else {
+		asn_enc_rval_t tmper;
+		asn_TYPE_member_t *elm = &td->elements[present-1];
+		void *memb_ptr;
+		const char *mname = elm->name;
+		unsigned int mlen = strlen(mname);
+
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+			if(!memb_ptr) ASN__ENCODE_FAILED;
+		} else {
+			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+		}
+
+		er.encoded = 0;
+
+                if(!(flags & XER_F_CANONICAL)) ASN__TEXT_INDENT(1, ilevel);
+		ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
+
+		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
+				ilevel + 1, flags, cb, app_key);
+		if(tmper.encoded == -1) return tmper;
+
+		ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);
+
+		er.encoded += 5 + (2 * mlen) + tmper.encoded;
+	}
+
+	if(!(flags & XER_F_CANONICAL)) ASN__TEXT_INDENT(1, ilevel - 1);
+
+	ASN__ENCODED_OK(er);
+cb_failed:
+	ASN__ENCODE_FAILED;
+}
+
+asn_dec_rval_t
+CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+	asn_dec_rval_t rv;
+	asn_per_constraint_t *ct;
+	asn_TYPE_member_t *elm;	/* CHOICE's element */
+	void *memb_ptr;
+	void **memb_ptr2;
+	void *st = *sptr;
+	int value;
+
+	if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
+		ASN__DECODE_FAILED;
+
+	/*
+	 * Create the target structure if it is not present already.
+	 */
+	if(!st) {
+		st = *sptr = CALLOC(1, specs->struct_size);
+		if(!st) ASN__DECODE_FAILED;
+	}
+
+	if(constraints) ct = &constraints->value;
+	else if(td->per_constraints) ct = &td->per_constraints->value;
+	else ct = 0;
+
+	if(ct && ct->flags & APC_EXTENSIBLE) {
+		value = per_get_few_bits(pd, 1);
+		if(value < 0) ASN__DECODE_STARVED;
+		if(value) ct = 0;	/* Not restricted */
+	}
+
+	if(ct && ct->range_bits >= 0) {
+		value = per_get_few_bits(pd, ct->range_bits);
+		if(value < 0) ASN__DECODE_STARVED;
+		ASN_DEBUG("CHOICE %s got index %d in range %d",
+			td->name, value, ct->range_bits);
+		if(value > ct->upper_bound)
+			ASN__DECODE_FAILED;
+	} else {
+		if(specs->ext_start == -1)
+			ASN__DECODE_FAILED;
+		value = uper_get_nsnnwn(pd);
+		if(value < 0) ASN__DECODE_STARVED;
+		value += specs->ext_start;
+		if(value >= td->elements_count)
+			ASN__DECODE_FAILED;
+	}
+
+	/* Adjust if canonical order is different from natural order */
+	if(specs->canonical_order)
+		value = specs->canonical_order[value];
+
+	/* Set presence to be able to free it later */
+	_set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
+
+	elm = &td->elements[value];
+	if(elm->flags & ATF_POINTER) {
+		/* Member is a pointer to another structure */
+		memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+	} else {
+		memb_ptr = (char *)st + elm->memb_offset;
+		memb_ptr2 = &memb_ptr;
+	}
+	ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
+
+	if(ct && ct->range_bits >= 0) {
+		rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
+			elm->per_constraints, memb_ptr2, pd);
+	} else {
+		rv = uper_open_type_get(opt_codec_ctx, elm->type,
+			elm->per_constraints, memb_ptr2, pd);
+	}
+
+	if(rv.code != RC_OK)
+		ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
+			elm->name, td->name, rv.code);
+	return rv;
+}
+   
+asn_enc_rval_t
+CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+	asn_TYPE_member_t *elm;	/* CHOICE's element */
+	asn_per_constraint_t *ct;
+	void *memb_ptr;
+	int present;
+	int present_enc;
+
+	if(!sptr) ASN__ENCODE_FAILED;
+
+	ASN_DEBUG("Encoding %s as CHOICE", td->name);
+
+	if(constraints) ct = &constraints->value;
+	else if(td->per_constraints) ct = &td->per_constraints->value;
+	else ct = 0;
+
+	present = _fetch_present_idx(sptr,
+		specs->pres_offset, specs->pres_size);
+
+	/*
+	 * If the structure was not initialized properly, it cannot be encoded:
+	 * can't deduce what to encode in the choice type.
+	 */
+	if(present <= 0 || present > td->elements_count)
+		ASN__ENCODE_FAILED;
+	else
+		present--;
+
+	ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
+
+	/* Adjust if canonical order is different from natural order */
+	if(specs->canonical_order)
+		present_enc = specs->canonical_order[present];
+	else
+		present_enc = present;
+
+	if(ct && ct->range_bits >= 0) {
+		if(present_enc < ct->lower_bound
+		|| present_enc > ct->upper_bound) {
+			if(ct->flags & APC_EXTENSIBLE) {
+				if(per_put_few_bits(po, 1, 1))
+					ASN__ENCODE_FAILED;
+			} else {
+				ASN__ENCODE_FAILED;
+			}
+			ct = 0;
+		}
+	}
+	if(ct && ct->flags & APC_EXTENSIBLE)
+		if(per_put_few_bits(po, 0, 1))
+			ASN__ENCODE_FAILED;
+
+	elm = &td->elements[present];
+	if(elm->flags & ATF_POINTER) {
+		/* Member is a pointer to another structure */
+		memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+		if(!memb_ptr) ASN__ENCODE_FAILED;
+	} else {
+		memb_ptr = (char *)sptr + elm->memb_offset;
+	}
+
+	if(ct && ct->range_bits >= 0) {
+		if(per_put_few_bits(po, present_enc, ct->range_bits))
+			ASN__ENCODE_FAILED;
+
+		return elm->type->uper_encoder(elm->type, elm->per_constraints,
+			memb_ptr, po);
+	} else {
+		asn_enc_rval_t rval;
+		if(specs->ext_start == -1)
+			ASN__ENCODE_FAILED;
+		if(uper_put_nsnnwn(po, present_enc - specs->ext_start))
+			ASN__ENCODE_FAILED;
+		if(uper_open_type_put(elm->type, elm->per_constraints,
+			memb_ptr, po))
+			ASN__ENCODE_FAILED;
+		rval.encoded = 0;
+		ASN__ENCODED_OK(rval);
+	}
+}
+   
+
+int
+CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+	int present;
+
+	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+
+	/*
+	 * Figure out which CHOICE element is encoded.
+	 */
+	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
+
+	/*
+	 * Print that element.
+	 */
+	if(present > 0 && present <= td->elements_count) {
+		asn_TYPE_member_t *elm = &td->elements[present-1];
+		const void *memb_ptr;
+
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
+			if(!memb_ptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+		} else {
+			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
+		}
+
+		/* Print member's name and stuff */
+		if(0) {
+			if(cb(elm->name, strlen(elm->name), app_key) < 0
+			|| cb(": ", 2, app_key) < 0)
+				return -1;
+		}
+
+		return elm->type->print_struct(elm->type, memb_ptr, ilevel,
+			cb, app_key);
+	} else {
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+	}
+}
+
+void
+CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
+	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+	int present;
+
+	if(!td || !ptr)
+		return;
+
+	ASN_DEBUG("Freeing %s as CHOICE", td->name);
+
+	/*
+	 * Figure out which CHOICE element is encoded.
+	 */
+	present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
+
+	/*
+	 * Free that element.
+	 */
+	if(present > 0 && present <= td->elements_count) {
+		asn_TYPE_member_t *elm = &td->elements[present-1];
+		void *memb_ptr;
+
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
+			if(memb_ptr)
+				ASN_STRUCT_FREE(*elm->type, memb_ptr);
+		} else {
+			memb_ptr = (void *)((char *)ptr + elm->memb_offset);
+			ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
+		}
+	}
+
+	if(!contents_only) {
+		FREEMEM(ptr);
+	}
+}
+
+
+/*
+ * The following functions functions offer protection against -fshort-enums,
+ * compatible with little- and big-endian machines.
+ * If assertion is triggered, either disable -fshort-enums, or add an entry
+ * here with the ->pres_size of your target stracture.
+ * Unless the target structure is packed, the ".present" member
+ * is guaranteed to be aligned properly. ASN.1 compiler itself does not
+ * produce packed code.
+ */
+static int
+_fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) {
+	const void *present_ptr;
+	int present;
+
+	present_ptr = ((const char *)struct_ptr) + pres_offset;
+
+	switch(pres_size) {
+	case sizeof(int):	present =   *(const int *)present_ptr; break;
+	case sizeof(short):	present = *(const short *)present_ptr; break;
+	case sizeof(char):	present =  *(const char *)present_ptr; break;
+	default:
+		/* ANSI C mandates enum to be equivalent to integer */
+		assert(pres_size != sizeof(int));
+		return 0;	/* If not aborted, pass back safe value */
+	}
+
+	return present;
+}
+
+static void
+_set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) {
+	void *present_ptr;
+	present_ptr = ((char *)struct_ptr) + pres_offset;
+
+	switch(pres_size) {
+	case sizeof(int):	*(int *)present_ptr   = present; break;
+	case sizeof(short):	*(short *)present_ptr = present; break;
+	case sizeof(char):	*(char *)present_ptr  = present; break;
+	default:
+		/* ANSI C mandates enum to be equivalent to integer */
+		assert(pres_size != sizeof(int));
+	}
+}
diff --git a/libkmod/pkcs7/asn1c-gen/constr_CHOICE.h b/libkmod/pkcs7/asn1c-gen/constr_CHOICE.h
new file mode 100644
index 000000000000..e824a2206e08
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_CHOICE.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_CONSTR_CHOICE_H_
+#define	_CONSTR_CHOICE_H_
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef const struct asn_CHOICE_specifics_s {
+	/*
+	 * Target structure description.
+	 */
+	int struct_size;	/* Size of the target structure. */
+	int ctx_offset;		/* Offset of the asn_codec_ctx_t member */
+	int pres_offset;	/* Identifier of the present member */
+	int pres_size;		/* Size of the identifier (enum) */
+
+	/*
+	 * Tags to members mapping table.
+	 */
+	const asn_TYPE_tag2member_t *tag2el;
+	int tag2el_count;
+
+	/* Canonical ordering of CHOICE elements, for PER */
+	int *canonical_order;
+
+	/*
+	 * Extensions-related stuff.
+	 */
+	int ext_start;		/* First member of extensions, or -1 */
+} asn_CHOICE_specifics_t;
+
+/*
+ * A set specialized functions dealing with the CHOICE type.
+ */
+asn_struct_free_f CHOICE_free;
+asn_struct_print_f CHOICE_print;
+asn_constr_check_f CHOICE_constraint;
+ber_type_decoder_f CHOICE_decode_ber;
+der_type_encoder_f CHOICE_encode_der;
+xer_type_decoder_f CHOICE_decode_xer;
+xer_type_encoder_f CHOICE_encode_xer;
+per_type_decoder_f CHOICE_decode_uper;
+per_type_encoder_f CHOICE_encode_uper;
+asn_outmost_tag_f CHOICE_outmost_tag;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _CONSTR_CHOICE_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c b/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c
new file mode 100644
index 000000000000..5923023dee1d
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c
@@ -0,0 +1,1425 @@
+/*-
+ * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_SEQUENCE.h>
+#include <per_opentype.h>
+
+/*
+ * Number of bytes left for this structure.
+ * (ctx->left) indicates the number of bytes _transferred_ for the structure.
+ * (size) contains the number of bytes in the buffer passed.
+ */
+#define	LEFT	((size<(size_t)ctx->left)?size:(size_t)ctx->left)
+
+/*
+ * If the subprocessor function returns with an indication that it wants
+ * more data, it may well be a fatal decoding problem, because the
+ * size is constrained by the <TLV>'s L, even if the buffer size allows
+ * reading more data.
+ * For example, consider the buffer containing the following TLVs:
+ * <T:5><L:1><V> <T:6>...
+ * The TLV length clearly indicates that one byte is expected in V, but
+ * if the V processor returns with "want more data" even if the buffer
+ * contains way more data than the V processor have seen.
+ */
+#define	SIZE_VIOLATION	(ctx->left >= 0 && (size_t)ctx->left <= size)
+
+/*
+ * This macro "eats" the part of the buffer which is definitely "consumed",
+ * i.e. was correctly converted into local representation or rightfully skipped.
+ */
+#undef	ADVANCE
+#define	ADVANCE(num_bytes)	do {		\
+		size_t num = num_bytes;		\
+		ptr = ((const char *)ptr) + num; \
+		size -= num;			\
+		if(ctx->left >= 0)		\
+			ctx->left -= num;	\
+		consumed_myself += num;		\
+	} while(0)
+
+/*
+ * Switch to the next phase of parsing.
+ */
+#undef	NEXT_PHASE
+#undef	PHASE_OUT
+#define	NEXT_PHASE(ctx)	do {			\
+		ctx->phase++;			\
+		ctx->step = 0;			\
+	} while(0)
+#define	PHASE_OUT(ctx)	do { ctx->phase = 10; } while(0)
+
+/*
+ * Return a standardized complex structure.
+ */
+#undef	RETURN
+#define	RETURN(_code)	do {			\
+		rval.code = _code;		\
+		rval.consumed = consumed_myself;\
+		return rval;			\
+	} while(0)
+
+/*
+ * Check whether we are inside the extensions group.
+ */
+#define	IN_EXTENSION_GROUP(specs, memb_idx)	\
+	( ((memb_idx) > (specs)->ext_after)	\
+	&&((memb_idx) < (specs)->ext_before))
+
+
+/*
+ * Tags are canonically sorted in the tag2element map.
+ */
+static int
+_t2e_cmp(const void *ap, const void *bp) {
+	const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
+	const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
+
+	int a_class = BER_TAG_CLASS(a->el_tag);
+	int b_class = BER_TAG_CLASS(b->el_tag);
+
+	if(a_class == b_class) {
+		ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
+		ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
+
+		if(a_value == b_value) {
+			if(a->el_no > b->el_no)
+				return 1;
+			/*
+			 * Important: we do not check
+			 * for a->el_no <= b->el_no!
+			 */
+			return 0;
+		} else if(a_value < b_value)
+			return -1;
+		else
+			return 1;
+	} else if(a_class < b_class) {
+		return -1;
+	} else {
+		return 1;
+	}
+}
+
+
+/*
+ * The decoder of the SEQUENCE type.
+ */
+asn_dec_rval_t
+SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+	void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
+	/*
+	 * Bring closer parts of structure description.
+	 */
+	asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
+	asn_TYPE_member_t *elements = td->elements;
+
+	/*
+	 * Parts of the structure being constructed.
+	 */
+	void *st = *struct_ptr;	/* Target structure. */
+	asn_struct_ctx_t *ctx;	/* Decoder context */
+
+	ber_tlv_tag_t tlv_tag;	/* T from TLV */
+	asn_dec_rval_t rval;	/* Return code from subparsers */
+
+	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
+	int edx;			/* SEQUENCE element's index */
+
+	ASN_DEBUG("Decoding %s as SEQUENCE", td->name);
+	
+	/*
+	 * Create the target structure if it is not present already.
+	 */
+	if(st == 0) {
+		st = *struct_ptr = CALLOC(1, specs->struct_size);
+		if(st == 0) {
+			RETURN(RC_FAIL);
+		}
+	}
+
+	/*
+	 * Restore parsing context.
+	 */
+	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
+	
+	/*
+	 * Start to parse where left previously
+	 */
+	switch(ctx->phase) {
+	case 0:
+		/*
+		 * PHASE 0.
+		 * Check that the set of tags associated with given structure
+		 * perfectly fits our expectations.
+		 */
+
+		rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
+			tag_mode, 1, &ctx->left, 0);
+		if(rval.code != RC_OK) {
+			ASN_DEBUG("%s tagging check failed: %d",
+				td->name, rval.code);
+			return rval;
+		}
+
+		if(ctx->left >= 0)
+			ctx->left += rval.consumed; /* ?Substracted below! */
+		ADVANCE(rval.consumed);
+
+		NEXT_PHASE(ctx);
+
+		ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
+			(long)ctx->left, (long)size);
+
+		/* Fall through */
+	case 1:
+		/*
+		 * PHASE 1.
+		 * From the place where we've left it previously,
+		 * try to decode the next member from the list of
+		 * this structure's elements.
+		 * (ctx->step) stores the member being processed
+		 * between invocations and the microphase {0,1} of parsing
+		 * that member:
+		 * 	step = (<member_number> * 2 + <microphase>).
+		 */
+	  for(edx = (ctx->step >> 1); edx < td->elements_count;
+			edx++, ctx->step = (ctx->step & ~1) + 2) {
+		void *memb_ptr;		/* Pointer to the member */
+		void **memb_ptr2;	/* Pointer to that pointer */
+		ssize_t tag_len;	/* Length of TLV's T */
+		int opt_edx_end;	/* Next non-optional element */
+		int use_bsearch;
+		int n;
+
+		if(ctx->step & 1)
+			goto microphase2;
+
+		/*
+		 * MICROPHASE 1: Synchronize decoding.
+		 */
+		ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d"
+				" opt=%d ec=%d",
+			td->name, (int)ctx->left, edx,
+			elements[edx].flags, elements[edx].optional,
+			td->elements_count);
+
+		if(ctx->left == 0	/* No more stuff is expected */
+		&& (
+			/* Explicit OPTIONAL specification reaches the end */
+			(edx + elements[edx].optional
+					== td->elements_count)
+			||
+			/* All extensions are optional */
+			(IN_EXTENSION_GROUP(specs, edx)
+				&& specs->ext_before > td->elements_count)
+		   )
+		) {
+			ASN_DEBUG("End of SEQUENCE %s", td->name);
+			/*
+			 * Found the legitimate end of the structure.
+			 */
+			PHASE_OUT(ctx);
+			RETURN(RC_OK);
+		}
+
+		/*
+		 * Fetch the T from TLV.
+		 */
+		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
+		ASN_DEBUG("Current tag in %s SEQUENCE for element %d "
+			"(%s) is %s encoded in %d bytes, of frame %ld",
+			td->name, edx, elements[edx].name,
+			ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT);
+		switch(tag_len) {
+		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
+			/* Fall through */
+		case -1: RETURN(RC_FAIL);
+		}
+
+		if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
+			if(LEFT < 2) {
+				if(SIZE_VIOLATION)
+					RETURN(RC_FAIL);
+				else
+					RETURN(RC_WMORE);
+			} else if(((const uint8_t *)ptr)[1] == 0) {
+			ASN_DEBUG("edx = %d, opt = %d, ec=%d",
+				edx, elements[edx].optional,
+				td->elements_count);
+				if((edx + elements[edx].optional
+					== td->elements_count)
+				|| (IN_EXTENSION_GROUP(specs, edx)
+					&& specs->ext_before
+						> td->elements_count)) {
+					/*
+					 * Yeah, baby! Found the terminator
+					 * of the indefinite length structure.
+					 */
+					/*
+					 * Proceed to the canonical
+					 * finalization function.
+					 * No advancing is necessary.
+					 */
+					goto phase3;
+				}
+			}
+		}
+
+		/*
+		 * Find the next available type with this tag.
+		 */
+		use_bsearch = 0;
+		opt_edx_end = edx + elements[edx].optional + 1;
+		if(opt_edx_end > td->elements_count)
+			opt_edx_end = td->elements_count;	/* Cap */
+		else if(opt_edx_end - edx > 8) {
+			/* Limit the scope of linear search... */
+			opt_edx_end = edx + 8;
+			use_bsearch = 1;
+			/* ... and resort to bsearch() */
+		}
+		for(n = edx; n < opt_edx_end; n++) {
+			if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {
+				/*
+				 * Found element corresponding to the tag
+				 * being looked at.
+				 * Reposition over the right element.
+				 */
+				edx = n;
+				ctx->step = 1 + 2 * edx;	/* Remember! */
+				goto microphase2;
+			} else if(elements[n].flags & ATF_OPEN_TYPE) {
+				/*
+				 * This is the ANY type, which may bear
+				 * any flag whatsoever.
+				 */
+				edx = n;
+				ctx->step = 1 + 2 * edx;	/* Remember! */
+				goto microphase2;
+			} else if(elements[n].tag == (ber_tlv_tag_t)-1) {
+				use_bsearch = 1;
+				break;
+			}
+		}
+		if(use_bsearch) {
+			/*
+			 * Resort to a binary search over
+			 * sorted array of tags.
+			 */
+			const asn_TYPE_tag2member_t *t2m;
+			asn_TYPE_tag2member_t key;
+			key.el_tag = tlv_tag;
+			key.el_no = edx;
+			t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
+				specs->tag2el, specs->tag2el_count,
+				sizeof(specs->tag2el[0]), _t2e_cmp);
+			if(t2m) {
+				const asn_TYPE_tag2member_t *best = 0;
+				const asn_TYPE_tag2member_t *t2m_f, *t2m_l;
+				int edx_max = edx + elements[edx].optional;
+				/*
+				 * Rewind to the first element with that tag,
+				 * `cause bsearch() does not guarantee order.
+				 */
+				t2m_f = t2m + t2m->toff_first;
+				t2m_l = t2m + t2m->toff_last;
+				for(t2m = t2m_f; t2m <= t2m_l; t2m++) {
+					if(t2m->el_no > edx_max) break;
+					if(t2m->el_no < edx) continue;
+					best = t2m;
+				}
+				if(best) {
+					edx = best->el_no;
+					ctx->step = 1 + 2 * edx;
+					goto microphase2;
+				}
+			}
+			n = opt_edx_end;
+		}
+		if(n == opt_edx_end) {
+			/*
+			 * If tag is unknown, it may be either
+			 * an unknown (thus, incorrect) tag,
+			 * or an extension (...),
+			 * or an end of the indefinite-length structure.
+			 */
+			if(!IN_EXTENSION_GROUP(specs,
+				edx + elements[edx].optional)) {
+				ASN_DEBUG("Unexpected tag %s (at %d)",
+					ber_tlv_tag_string(tlv_tag), edx);
+				ASN_DEBUG("Expected tag %s (%s)%s",
+					ber_tlv_tag_string(elements[edx].tag),
+					elements[edx].name,
+					elements[edx].optional
+						?" or alternatives":"");
+				RETURN(RC_FAIL);
+			} else {
+				/* Skip this tag */
+				ssize_t skip;
+				edx += elements[edx].optional;
+
+				ASN_DEBUG("Skipping unexpected %s (at %d)",
+					ber_tlv_tag_string(tlv_tag), edx);
+				skip = ber_skip_length(opt_codec_ctx,
+					BER_TLV_CONSTRUCTED(ptr),
+					(const char *)ptr + tag_len,
+					LEFT - tag_len);
+				ASN_DEBUG("Skip length %d in %s",
+					(int)skip, td->name);
+				switch(skip) {
+				case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
+					/* Fall through */
+				case -1: RETURN(RC_FAIL);
+				}
+
+				ADVANCE(skip + tag_len);
+				ctx->step -= 2;
+				edx--;
+				continue;  /* Try again with the next tag */
+			}
+		}
+
+		/*
+		 * MICROPHASE 2: Invoke the member-specific decoder.
+		 */
+		ctx->step |= 1;		/* Confirm entering next microphase */
+	microphase2:
+		ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);
+		
+		/*
+		 * Compute the position of the member inside a structure,
+		 * and also a type of containment (it may be contained
+		 * as pointer or using inline inclusion).
+		 */
+		if(elements[edx].flags & ATF_POINTER) {
+			/* Member is a pointer to another structure */
+			memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
+		} else {
+			/*
+			 * A pointer to a pointer
+			 * holding the start of the structure
+			 */
+			memb_ptr = (char *)st + elements[edx].memb_offset;
+			memb_ptr2 = &memb_ptr;
+		}
+		/*
+		 * Invoke the member fetch routine according to member's type
+		 */
+		rval = elements[edx].type->ber_decoder(opt_codec_ctx,
+				elements[edx].type,
+				memb_ptr2, ptr, LEFT,
+				elements[edx].tag_mode);
+		ASN_DEBUG("In %s SEQUENCE decoded %d %s of %d "
+			"in %d bytes rval.code %d, size=%d",
+			td->name, edx, elements[edx].type->name,
+			(int)LEFT, (int)rval.consumed, rval.code, (int)size);
+		switch(rval.code) {
+		case RC_OK:
+			break;
+		case RC_WMORE: /* More data expected */
+			if(!SIZE_VIOLATION) {
+				ADVANCE(rval.consumed);
+				RETURN(RC_WMORE);
+			}
+			ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)",
+				(long)ctx->left, (long)size);
+			/* Fall through */
+		case RC_FAIL: /* Fatal error */
+			RETURN(RC_FAIL);
+		} /* switch(rval) */
+		
+		ADVANCE(rval.consumed);
+	  }	/* for(all structure members) */
+
+	phase3:
+		ctx->phase = 3;
+	case 3:	/* 00 and other tags expected */
+	case 4:	/* only 00's expected */
+
+		ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",
+			td->name, (long)ctx->left, (long)size);
+
+		/*
+		 * Skip everything until the end of the SEQUENCE.
+		 */
+		while(ctx->left) {
+			ssize_t tl, ll;
+
+			tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
+			switch(tl) {
+			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
+				/* Fall through */
+			case -1: RETURN(RC_FAIL);
+			}
+
+			/*
+			 * If expected <0><0>...
+			 */
+			if(ctx->left < 0
+				&& ((const uint8_t *)ptr)[0] == 0) {
+				if(LEFT < 2) {
+					if(SIZE_VIOLATION)
+						RETURN(RC_FAIL);
+					else
+						RETURN(RC_WMORE);
+				} else if(((const uint8_t *)ptr)[1] == 0) {
+					/*
+					 * Correctly finished with <0><0>.
+					 */
+					ADVANCE(2);
+					ctx->left++;
+					ctx->phase = 4;
+					continue;
+				}
+			}
+
+			if(!IN_EXTENSION_GROUP(specs, td->elements_count)
+			|| ctx->phase == 4) {
+				ASN_DEBUG("Unexpected continuation "
+					"of a non-extensible type "
+					"%s (SEQUENCE): %s",
+					td->name,
+					ber_tlv_tag_string(tlv_tag));
+				RETURN(RC_FAIL);
+			}
+
+			ll = ber_skip_length(opt_codec_ctx,
+				BER_TLV_CONSTRUCTED(ptr),
+				(const char *)ptr + tl, LEFT - tl);
+			switch(ll) {
+			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
+				/* Fall through */
+			case -1: RETURN(RC_FAIL);
+			}
+
+			ADVANCE(tl + ll);
+		}
+
+		PHASE_OUT(ctx);
+	}
+	
+	RETURN(RC_OK);
+}
+
+
+/*
+ * The DER encoder of the SEQUENCE type.
+ */
+asn_enc_rval_t
+SEQUENCE_encode_der(asn_TYPE_descriptor_t *td,
+	void *sptr, int tag_mode, ber_tlv_tag_t tag,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	size_t computed_size = 0;
+	asn_enc_rval_t erval;
+	ssize_t ret;
+	int edx;
+
+	ASN_DEBUG("%s %s as SEQUENCE",
+		cb?"Encoding":"Estimating", td->name);
+
+	/*
+	 * Gather the length of the underlying members sequence.
+	 */
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		void *memb_ptr;
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+			if(!memb_ptr) {
+				if(elm->optional) continue;
+				/* Mandatory element is missing */
+				ASN__ENCODE_FAILED;
+			}
+		} else {
+			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+		}
+		erval = elm->type->der_encoder(elm->type, memb_ptr,
+			elm->tag_mode, elm->tag,
+			0, 0);
+		if(erval.encoded == -1)
+			return erval;
+		computed_size += erval.encoded;
+		ASN_DEBUG("Member %d %s estimated %ld bytes",
+			edx, elm->name, (long)erval.encoded);
+	}
+
+	/*
+	 * Encode the TLV for the sequence itself.
+	 */
+	ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
+	ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size);
+	if(ret == -1)
+		ASN__ENCODE_FAILED;
+	erval.encoded = computed_size + ret;
+
+	if(!cb) ASN__ENCODED_OK(erval);
+
+	/*
+	 * Encode all members.
+	 */
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		asn_enc_rval_t tmperval;
+		void *memb_ptr;
+
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+			if(!memb_ptr) continue;
+		} else {
+			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+		}
+		tmperval = elm->type->der_encoder(elm->type, memb_ptr,
+			elm->tag_mode, elm->tag,
+			cb, app_key);
+		if(tmperval.encoded == -1)
+			return tmperval;
+		computed_size -= tmperval.encoded;
+		ASN_DEBUG("Member %d %s of SEQUENCE %s encoded in %ld bytes",
+			edx, elm->name, td->name, (long)tmperval.encoded);
+	}
+
+	if(computed_size != 0)
+		/*
+		 * Encoded size is not equal to the computed size.
+		 */
+		ASN__ENCODE_FAILED;
+
+	ASN__ENCODED_OK(erval);
+}
+
+
+#undef	XER_ADVANCE
+#define	XER_ADVANCE(num_bytes)	do {			\
+		size_t num = num_bytes;			\
+		buf_ptr = ((const char *)buf_ptr) + num;\
+		size -= num;				\
+		consumed_myself += num;			\
+	} while(0)
+
+/*
+ * Decode the XER (XML) data.
+ */
+asn_dec_rval_t
+SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+	void **struct_ptr, const char *opt_mname,
+		const void *buf_ptr, size_t size) {
+	/*
+	 * Bring closer parts of structure description.
+	 */
+	asn_SEQUENCE_specifics_t *specs
+		= (asn_SEQUENCE_specifics_t *)td->specifics;
+	asn_TYPE_member_t *elements = td->elements;
+	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
+
+	/*
+	 * ... and parts of the structure being constructed.
+	 */
+	void *st = *struct_ptr;	/* Target structure. */
+	asn_struct_ctx_t *ctx;	/* Decoder context */
+
+	asn_dec_rval_t rval;		/* Return value from a decoder */
+	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
+	int edx;			/* Element index */
+	int edx_end;
+
+	/*
+	 * Create the target structure if it is not present already.
+	 */
+	if(st == 0) {
+		st = *struct_ptr = CALLOC(1, specs->struct_size);
+		if(st == 0) RETURN(RC_FAIL);
+	}
+
+	/*
+	 * Restore parsing context.
+	 */
+	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
+
+
+	/*
+	 * Phases of XER/XML processing:
+	 * Phase 0: Check that the opening tag matches our expectations.
+	 * Phase 1: Processing body and reacting on closing tag.
+	 * Phase 2: Processing inner type.
+	 * Phase 3: Skipping unknown extensions.
+	 * Phase 4: PHASED OUT
+	 */
+	for(edx = ctx->step; ctx->phase <= 3;) {
+		pxer_chunk_type_e ch_type;	/* XER chunk type */
+		ssize_t ch_size;		/* Chunk size */
+		xer_check_tag_e tcv;		/* Tag check value */
+		asn_TYPE_member_t *elm;
+		int n;
+
+		/*
+		 * Go inside the inner member of a sequence.
+		 */
+		if(ctx->phase == 2) {
+			asn_dec_rval_t tmprval;
+			void *memb_ptr;		/* Pointer to the member */
+			void **memb_ptr2;	/* Pointer to that pointer */
+
+			elm = &td->elements[edx];
+
+			if(elm->flags & ATF_POINTER) {
+				/* Member is a pointer to another structure */
+				memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+			} else {
+				memb_ptr = (char *)st + elm->memb_offset;
+				memb_ptr2 = &memb_ptr;
+			}
+
+			/* Invoke the inner type decoder, m.b. multiple times */
+			tmprval = elm->type->xer_decoder(opt_codec_ctx,
+					elm->type, memb_ptr2, elm->name,
+					buf_ptr, size);
+			XER_ADVANCE(tmprval.consumed);
+			if(tmprval.code != RC_OK)
+				RETURN(tmprval.code);
+			ctx->phase = 1;	/* Back to body processing */
+			ctx->step = ++edx;
+			ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d",
+				ctx->phase, ctx->step);
+			/* Fall through */
+		}
+
+		/*
+		 * Get the next part of the XML stream.
+		 */
+		ch_size = xer_next_token(&ctx->context, buf_ptr, size,
+			&ch_type);
+		if(ch_size == -1) {
+		    RETURN(RC_FAIL);
+        } else {
+			switch(ch_type) {
+            case PXER_WMORE:
+                RETURN(RC_WMORE);
+			case PXER_COMMENT:	/* Got XML comment */
+			case PXER_TEXT:		/* Ignore free-standing text */
+				XER_ADVANCE(ch_size);	/* Skip silently */
+				continue;
+			case PXER_TAG:
+				break;	/* Check the rest down there */
+			}
+		}
+
+		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
+		ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]",
+			tcv, ctx->phase, xml_tag);
+
+		/* Skip the extensions section */
+		if(ctx->phase == 3) {
+			switch(xer_skip_unknown(tcv, &ctx->left)) {
+			case -1:
+				ctx->phase = 4;
+				RETURN(RC_FAIL);
+			case 0:
+				XER_ADVANCE(ch_size);
+				continue;
+			case 1:
+				XER_ADVANCE(ch_size);
+				ctx->phase = 1;
+				continue;
+			case 2:
+				ctx->phase = 1;
+				break;
+			}
+		}
+
+		switch(tcv) {
+		case XCT_CLOSING:
+			if(ctx->phase == 0) break;
+			ctx->phase = 0;
+			/* Fall through */
+		case XCT_BOTH:
+			if(ctx->phase == 0) {
+				if(edx >= td->elements_count
+				   ||
+				   /* Explicit OPTIONAL specs reaches the end */
+				    (edx + elements[edx].optional
+					== td->elements_count)
+				   ||
+				   /* All extensions are optional */
+				   (IN_EXTENSION_GROUP(specs, edx)
+					&& specs->ext_before
+						> td->elements_count)
+				) {
+					XER_ADVANCE(ch_size);
+					ctx->phase = 4;	/* Phase out */
+					RETURN(RC_OK);
+				} else {
+					ASN_DEBUG("Premature end of XER SEQUENCE");
+					RETURN(RC_FAIL);
+				}
+			}
+			/* Fall through */
+		case XCT_OPENING:
+			if(ctx->phase == 0) {
+				XER_ADVANCE(ch_size);
+				ctx->phase = 1;	/* Processing body phase */
+				continue;
+			}
+			/* Fall through */
+		case XCT_UNKNOWN_OP:
+		case XCT_UNKNOWN_BO:
+
+			ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%d",
+				tcv, ctx->phase, edx);
+			if(ctx->phase != 1) {
+				break;	/* Really unexpected */
+			}
+
+			if(edx < td->elements_count) {
+				/*
+				 * Search which member corresponds to this tag.
+				 */
+				edx_end = edx + elements[edx].optional + 1;
+				if(edx_end > td->elements_count)
+					edx_end = td->elements_count;
+				for(n = edx; n < edx_end; n++) {
+					elm = &td->elements[n];
+					tcv = xer_check_tag(buf_ptr,
+						ch_size, elm->name);
+					switch(tcv) {
+					case XCT_BOTH:
+					case XCT_OPENING:
+						/*
+						 * Process this member.
+						 */
+						ctx->step = edx = n;
+						ctx->phase = 2;
+						break;
+					case XCT_UNKNOWN_OP:
+					case XCT_UNKNOWN_BO:
+						continue;
+					default:
+						n = edx_end;
+						break;	/* Phase out */
+					}
+					break;
+				}
+				if(n != edx_end)
+					continue;
+			} else {
+				ASN_DEBUG("Out of defined members: %d/%d",
+					edx, td->elements_count);
+			}
+
+			/* It is expected extension */
+			if(IN_EXTENSION_GROUP(specs,
+				edx + (edx < td->elements_count
+					? elements[edx].optional : 0))) {
+				ASN_DEBUG("Got anticipated extension at %d",
+					edx);
+				/*
+				 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
+				 * By using a mask. Only record a pure
+				 * <opening> tags.
+				 */
+				if(tcv & XCT_CLOSING) {
+					/* Found </extension> without body */
+				} else {
+					ctx->left = 1;
+					ctx->phase = 3;	/* Skip ...'s */
+				}
+				XER_ADVANCE(ch_size);
+				continue;
+			}
+
+			/* Fall through */
+		default:
+			break;
+		}
+
+		ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]",
+			size>0?((const char *)buf_ptr)[0]:'.',
+			size>1?((const char *)buf_ptr)[1]:'.',
+			size>2?((const char *)buf_ptr)[2]:'.',
+			size>3?((const char *)buf_ptr)[3]:'.',
+			size>4?((const char *)buf_ptr)[4]:'.',
+			size>5?((const char *)buf_ptr)[5]:'.');
+		break;
+	}
+
+	ctx->phase = 4;	/* "Phase out" on hard failure */
+	RETURN(RC_FAIL);
+}
+
+asn_enc_rval_t
+SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_enc_rval_t er;
+	int xcan = (flags & XER_F_CANONICAL);
+	int edx;
+
+	if(!sptr)
+		ASN__ENCODE_FAILED;
+
+	er.encoded = 0;
+
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn_enc_rval_t tmper;
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		void *memb_ptr;
+		const char *mname = elm->name;
+		unsigned int mlen = strlen(mname);
+
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+			if(!memb_ptr) {
+				if(elm->optional)
+					continue;
+				/* Mandatory element is missing */
+				ASN__ENCODE_FAILED;
+			}
+		} else {
+			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+		}
+
+		if(!xcan) ASN__TEXT_INDENT(1, ilevel);
+		ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
+
+		/* Print the member itself */
+		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
+			ilevel + 1, flags, cb, app_key);
+		if(tmper.encoded == -1) return tmper;
+
+		ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);
+		er.encoded += 5 + (2 * mlen) + tmper.encoded;
+	}
+
+	if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
+
+	ASN__ENCODED_OK(er);
+cb_failed:
+	ASN__ENCODE_FAILED;
+}
+
+int
+SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	int edx;
+	int ret;
+
+	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+
+	/* Dump preamble */
+	if(cb(td->name, strlen(td->name), app_key) < 0
+	|| cb(" ::= {", 6, app_key) < 0)
+		return -1;
+
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		const void *memb_ptr;
+
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
+			if(!memb_ptr) {
+				if(elm->optional) continue;
+				/* Print <absent> line */
+				/* Fall through */
+			}
+		} else {
+			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
+		}
+
+		/* Indentation */
+		_i_INDENT(1);
+
+		/* Print the member's name and stuff */
+		if(cb(elm->name, strlen(elm->name), app_key) < 0
+		|| cb(": ", 2, app_key) < 0)
+			return -1;
+
+		/* Print the member itself */
+		ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1,
+			cb, app_key);
+		if(ret) return ret;
+	}
+
+	ilevel--;
+	_i_INDENT(1);
+
+	return (cb("}", 1, app_key) < 0) ? -1 : 0;
+}
+
+void
+SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
+	int edx;
+
+	if(!td || !sptr)
+		return;
+
+	ASN_DEBUG("Freeing %s as SEQUENCE", td->name);
+
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		void *memb_ptr;
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+			if(memb_ptr)
+				ASN_STRUCT_FREE(*elm->type, memb_ptr);
+		} else {
+			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+			ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
+		}
+	}
+
+	if(!contents_only) {
+		FREEMEM(sptr);
+	}
+}
+
+int
+SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	int edx;
+
+	if(!sptr) {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: value not given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+
+	/*
+	 * Iterate over structure members and check their validity.
+	 */
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		const void *memb_ptr;
+
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
+			if(!memb_ptr) {
+				if(elm->optional)
+					continue;
+				ASN__CTFAIL(app_key, td, sptr,
+				"%s: mandatory element %s absent (%s:%d)",
+				td->name, elm->name, __FILE__, __LINE__);
+				return -1;
+			}
+		} else {
+			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
+		}
+
+		if(elm->memb_constraints) {
+			int ret = elm->memb_constraints(elm->type, memb_ptr,
+				ctfailcb, app_key);
+			if(ret) return ret;
+		} else {
+			int ret = elm->type->check_constraints(elm->type,
+				memb_ptr, ctfailcb, app_key);
+			if(ret) return ret;
+			/*
+			 * Cannot inherit it earlier:
+			 * need to make sure we get the updated version.
+			 */
+			elm->memb_constraints = elm->type->check_constraints;
+		}
+	}
+
+	return 0;
+}
+
+asn_dec_rval_t
+SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+	asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
+	void *st = *sptr;	/* Target structure. */
+	int extpresent;		/* Extension additions are present */
+	uint8_t *opres;		/* Presence of optional root members */
+	asn_per_data_t opmd;
+	asn_dec_rval_t rv;
+	int edx;
+
+	(void)constraints;
+
+	if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
+		ASN__DECODE_FAILED;
+
+	if(!st) {
+		st = *sptr = CALLOC(1, specs->struct_size);
+		if(!st) ASN__DECODE_FAILED;
+	}
+
+	ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name);
+
+	/* Handle extensions */
+	if(specs->ext_before >= 0) {
+		extpresent = per_get_few_bits(pd, 1);
+		if(extpresent < 0) ASN__DECODE_STARVED;
+	} else {
+		extpresent = 0;
+	}
+
+	/* Prepare a place and read-in the presence bitmap */
+	memset(&opmd, 0, sizeof(opmd));
+	if(specs->roms_count) {
+		opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);
+		if(!opres) ASN__DECODE_FAILED;
+		/* Get the presence map */
+		if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {
+			FREEMEM(opres);
+			ASN__DECODE_STARVED;
+		}
+		opmd.buffer = opres;
+		opmd.nbits = specs->roms_count;
+		ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",
+			td->name, specs->roms_count, *opres);
+	} else {
+		opres = 0;
+	}
+
+	/*
+	 * Get the sequence ROOT elements.
+	 */
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		void *memb_ptr;		/* Pointer to the member */
+		void **memb_ptr2;	/* Pointer to that pointer */
+
+		if(IN_EXTENSION_GROUP(specs, edx))
+			continue;
+
+		/* Fetch the pointer to this member */
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+		} else {
+			memb_ptr = (char *)st + elm->memb_offset;
+			memb_ptr2 = &memb_ptr;
+		}
+
+		/* Deal with optionality */
+		if(elm->optional) {
+			int present = per_get_few_bits(&opmd, 1);
+			ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)",
+				td->name, elm->name, present,
+				(int)opmd.nboff, (int)opmd.nbits);
+			if(present == 0) {
+				/* This element is not present */
+				if(elm->default_value) {
+					/* Fill-in DEFAULT */
+					if(elm->default_value(1, memb_ptr2)) {
+						FREEMEM(opres);
+						ASN__DECODE_FAILED;
+					}
+					ASN_DEBUG("Filled-in default");
+				}
+				/* The member is just not present */
+				continue;
+			}
+			/* Fall through */
+		}
+
+		/* Fetch the member from the stream */
+		ASN_DEBUG("Decoding member %s in %s", elm->name, td->name);
+		rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
+			elm->per_constraints, memb_ptr2, pd);
+		if(rv.code != RC_OK) {
+			ASN_DEBUG("Failed decode %s in %s",
+				elm->name, td->name);
+			FREEMEM(opres);
+			return rv;
+		}
+	}
+
+	/* Optionality map is not needed anymore */
+	FREEMEM(opres);
+
+	/*
+	 * Deal with extensions.
+	 */
+	if(extpresent) {
+		ssize_t bmlength;
+		uint8_t *epres;		/* Presence of extension members */
+		asn_per_data_t epmd;
+
+		bmlength = uper_get_nslength(pd);
+		if(bmlength < 0) ASN__DECODE_STARVED;
+
+		ASN_DEBUG("Extensions %ld present in %s", (long)bmlength, td->name);
+
+		epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
+		if(!epres) ASN__DECODE_STARVED;
+
+		/* Get the extensions map */
+		if(per_get_many_bits(pd, epres, 0, bmlength)) {
+			FREEMEM(epres);
+			ASN__DECODE_STARVED;
+		}
+
+		memset(&epmd, 0, sizeof(epmd));
+		epmd.buffer = epres;
+		epmd.nbits = bmlength;
+		ASN_DEBUG("Read in extensions bitmap for %s of %ld bits (%x..)",
+			td->name, (long)bmlength, *epres);
+
+	    /* Go over extensions and read them in */
+	    for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		void *memb_ptr;		/* Pointer to the member */
+		void **memb_ptr2;	/* Pointer to that pointer */
+		int present;
+
+		if(!IN_EXTENSION_GROUP(specs, edx)) {
+			ASN_DEBUG("%d is not extension", edx);
+			continue;
+		}
+
+		/* Fetch the pointer to this member */
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+		} else {
+			memb_ptr = (void *)((char *)st + elm->memb_offset);
+			memb_ptr2 = &memb_ptr;
+		}
+
+		present = per_get_few_bits(&epmd, 1);
+		if(present <= 0) {
+			if(present < 0) break;	/* No more extensions */
+			continue;
+		}
+
+		ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
+		rv = uper_open_type_get(opt_codec_ctx, elm->type,
+			elm->per_constraints, memb_ptr2, pd);
+		if(rv.code != RC_OK) {
+			FREEMEM(epres);
+			return rv;
+		}
+	    }
+
+		/* Skip over overflow extensions which aren't present
+		 * in this system's version of the protocol */
+		for(;;) {
+			ASN_DEBUG("Getting overflow extensions");
+			switch(per_get_few_bits(&epmd, 1)) {
+			case -1: break;
+			case 0: continue;
+			default:
+				if(uper_open_type_skip(opt_codec_ctx, pd)) {
+					FREEMEM(epres);
+					ASN__DECODE_STARVED;
+				}
+			}
+			break;
+		}
+
+		FREEMEM(epres);
+	}
+
+	/* Fill DEFAULT members in extensions */
+	for(edx = specs->roms_count; edx < specs->roms_count
+			+ specs->aoms_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		void **memb_ptr2;	/* Pointer to member pointer */
+
+		if(!elm->default_value) continue;
+
+		/* Fetch the pointer to this member */
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr2 = (void **)((char *)st
+					+ elm->memb_offset);
+			if(*memb_ptr2) continue;
+		} else {
+			continue;	/* Extensions are all optionals */
+		}
+
+		/* Set default value */
+		if(elm->default_value(1, memb_ptr2)) {
+			ASN__DECODE_FAILED;
+		}
+	}
+
+	rv.consumed = 0;
+	rv.code = RC_OK;
+	return rv;
+}
+
+static int
+SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr,
+		asn_per_outp_t *po1, asn_per_outp_t *po2) {
+	asn_SEQUENCE_specifics_t *specs
+		= (asn_SEQUENCE_specifics_t *)td->specifics;
+	int exts_present = 0;
+	int exts_count = 0;
+	int edx;
+
+	if(specs->ext_before < 0)
+		return 0;
+
+	/* Find out which extensions are present */
+	for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		void *memb_ptr;		/* Pointer to the member */
+		void **memb_ptr2;	/* Pointer to that pointer */
+		int present;
+
+		if(!IN_EXTENSION_GROUP(specs, edx)) {
+			ASN_DEBUG("%s (@%d) is not extension", elm->type->name, edx);
+			continue;
+		}
+
+		/* Fetch the pointer to this member */
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+			present = (*memb_ptr2 != 0);
+		} else {
+			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+			memb_ptr2 = &memb_ptr;
+			present = 1;
+		}
+
+		ASN_DEBUG("checking %s (@%d) present => %d",
+			elm->type->name, edx, present);
+		exts_count++;
+		exts_present += present;
+
+		/* Encode as presence marker */
+		if(po1 && per_put_few_bits(po1, present, 1))
+			return -1;
+		/* Encode as open type field */
+		if(po2 && present && uper_open_type_put(elm->type,
+				elm->per_constraints, *memb_ptr2, po2))
+			return -1;
+
+	}
+
+	return exts_present ? exts_count : 0;
+}
+
+asn_enc_rval_t
+SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+	asn_SEQUENCE_specifics_t *specs
+		= (asn_SEQUENCE_specifics_t *)td->specifics;
+	asn_enc_rval_t er;
+	int n_extensions;
+	int edx;
+	int i;
+
+	(void)constraints;
+
+	if(!sptr)
+		ASN__ENCODE_FAILED;
+
+	er.encoded = 0;
+
+	ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
+
+
+	/*
+	 * X.691#18.1 Whether structure is extensible
+	 * and whether to encode extensions
+	 */
+	if(specs->ext_before >= 0) {
+		n_extensions = SEQUENCE_handle_extensions(td, sptr, 0, 0);
+		per_put_few_bits(po, n_extensions ? 1 : 0, 1);
+	} else {
+		n_extensions = 0;	/* There are no extensions to encode */
+	}
+
+	/* Encode a presence bitmap */
+	for(i = 0; i < specs->roms_count; i++) {
+		asn_TYPE_member_t *elm;
+		void *memb_ptr;		/* Pointer to the member */
+		void **memb_ptr2;	/* Pointer to that pointer */
+		int present;
+
+		edx = specs->oms[i];
+		elm = &td->elements[edx];
+
+		/* Fetch the pointer to this member */
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+			present = (*memb_ptr2 != 0);
+		} else {
+			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+			memb_ptr2 = &memb_ptr;
+			present = 1;
+		}
+
+		/* Eliminate default values */
+		if(present && elm->default_value
+		&& elm->default_value(0, memb_ptr2) == 1)
+			present = 0;
+
+		ASN_DEBUG("Element %s %s %s->%s is %s",
+			elm->flags & ATF_POINTER ? "ptr" : "inline",
+			elm->default_value ? "def" : "wtv",
+			td->name, elm->name, present ? "present" : "absent");
+		if(per_put_few_bits(po, present, 1))
+			ASN__ENCODE_FAILED;
+	}
+
+	/*
+	 * Encode the sequence ROOT elements.
+	 */
+	ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before);
+	for(edx = 0; edx < ((specs->ext_after < 0)
+		? td->elements_count : specs->ext_before - 1); edx++) {
+
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		void *memb_ptr;		/* Pointer to the member */
+		void **memb_ptr2;	/* Pointer to that pointer */
+
+		if(IN_EXTENSION_GROUP(specs, edx))
+			continue;
+
+		ASN_DEBUG("About to encode %s", elm->type->name);
+
+		/* Fetch the pointer to this member */
+		if(elm->flags & ATF_POINTER) {
+			memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+			if(!*memb_ptr2) {
+				ASN_DEBUG("Element %s %d not present",
+					elm->name, edx);
+				if(elm->optional)
+					continue;
+				/* Mandatory element is missing */
+				ASN__ENCODE_FAILED;
+			}
+		} else {
+			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+			memb_ptr2 = &memb_ptr;
+		}
+
+		/* Eliminate default values */
+		if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
+			continue;
+
+		ASN_DEBUG("Encoding %s->%s", td->name, elm->name);
+		er = elm->type->uper_encoder(elm->type, elm->per_constraints,
+			*memb_ptr2, po);
+		if(er.encoded == -1)
+			return er;
+	}
+
+	/* No extensions to encode */
+	if(!n_extensions) ASN__ENCODED_OK(er);
+
+	ASN_DEBUG("Length of %d bit-map", n_extensions);
+	/* #18.8. Write down the presence bit-map length. */
+	if(uper_put_nslength(po, n_extensions))
+		ASN__ENCODE_FAILED;
+
+	ASN_DEBUG("Bit-map of %d elements", n_extensions);
+	/* #18.7. Encoding the extensions presence bit-map. */
+	/* TODO: act upon NOTE in #18.7 for canonical PER */
+	if(SEQUENCE_handle_extensions(td, sptr, po, 0) != n_extensions)
+		ASN__ENCODE_FAILED;
+
+	ASN_DEBUG("Writing %d extensions", n_extensions);
+	/* #18.9. Encode extensions as open type fields. */
+	if(SEQUENCE_handle_extensions(td, sptr, 0, po) != n_extensions)
+		ASN__ENCODE_FAILED;
+
+	ASN__ENCODED_OK(er);
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h b/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h
new file mode 100644
index 000000000000..c2aeb6676757
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_CONSTR_SEQUENCE_H_
+#define	_CONSTR_SEQUENCE_H_
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef const struct asn_SEQUENCE_specifics_s {
+	/*
+	 * Target structure description.
+	 */
+	int struct_size;	/* Size of the target structure. */
+	int ctx_offset;		/* Offset of the asn_struct_ctx_t member */
+
+	/*
+	 * Tags to members mapping table (sorted).
+	 */
+	const asn_TYPE_tag2member_t *tag2el;
+	int tag2el_count;
+
+	/*
+	 * Optional members of the extensions root (roms) or additions (aoms).
+	 * Meaningful for PER.
+	 */
+	const int *oms;		/* Optional MemberS */
+	int  roms_count;	/* Root optional members count */
+	int  aoms_count;	/* Additions optional members count */
+
+	/*
+	 * Description of an extensions group.
+	 */
+	int ext_after;		/* Extensions start after this member */
+	int ext_before;		/* Extensions stop before this member */
+} asn_SEQUENCE_specifics_t;
+
+
+/*
+ * A set specialized functions dealing with the SEQUENCE type.
+ */
+asn_struct_free_f SEQUENCE_free;
+asn_struct_print_f SEQUENCE_print;
+asn_constr_check_f SEQUENCE_constraint;
+ber_type_decoder_f SEQUENCE_decode_ber;
+der_type_encoder_f SEQUENCE_encode_der;
+xer_type_decoder_f SEQUENCE_decode_xer;
+xer_type_encoder_f SEQUENCE_encode_xer;
+per_type_decoder_f SEQUENCE_decode_uper;
+per_type_encoder_f SEQUENCE_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _CONSTR_SEQUENCE_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c b/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c
new file mode 100644
index 000000000000..8a08ee8aa16a
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c
@@ -0,0 +1,208 @@
+/*-
+ * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_SEQUENCE_OF.h>
+#include <asn_SEQUENCE_OF.h>
+
+/*
+ * The DER encoder of the SEQUENCE OF type.
+ */
+asn_enc_rval_t
+SEQUENCE_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
+	int tag_mode, ber_tlv_tag_t tag,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_TYPE_member_t *elm = td->elements;
+	asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(ptr);
+	size_t computed_size = 0;
+	ssize_t encoding_size = 0;
+	asn_enc_rval_t erval;
+	int edx;
+
+	ASN_DEBUG("Estimating size of SEQUENCE OF %s", td->name);
+
+	/*
+	 * Gather the length of the underlying members sequence.
+	 */
+	for(edx = 0; edx < list->count; edx++) {
+		void *memb_ptr = list->array[edx];
+		if(!memb_ptr) continue;
+		erval = elm->type->der_encoder(elm->type, memb_ptr,
+			0, elm->tag,
+			0, 0);
+		if(erval.encoded == -1)
+			return erval;
+		computed_size += erval.encoded;
+	}
+
+	/*
+	 * Encode the TLV for the sequence itself.
+	 */
+	encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,
+		cb, app_key);
+	if(encoding_size == -1) {
+		erval.encoded = -1;
+		erval.failed_type = td;
+		erval.structure_ptr = ptr;
+		return erval;
+	}
+
+	computed_size += encoding_size;
+	if(!cb) {
+		erval.encoded = computed_size;
+		ASN__ENCODED_OK(erval);
+	}
+
+	ASN_DEBUG("Encoding members of SEQUENCE OF %s", td->name);
+
+	/*
+	 * Encode all members.
+	 */
+	for(edx = 0; edx < list->count; edx++) {
+		void *memb_ptr = list->array[edx];
+		if(!memb_ptr) continue;
+		erval = elm->type->der_encoder(elm->type, memb_ptr,
+			0, elm->tag,
+			cb, app_key);
+		if(erval.encoded == -1)
+			return erval;
+		encoding_size += erval.encoded;
+	}
+
+	if(computed_size != (size_t)encoding_size) {
+		/*
+		 * Encoded size is not equal to the computed size.
+		 */
+		erval.encoded = -1;
+		erval.failed_type = td;
+		erval.structure_ptr = ptr;
+	} else {
+		erval.encoded = computed_size;
+		erval.structure_ptr = 0;
+		erval.failed_type = 0;
+	}
+
+	return erval;
+}
+
+asn_enc_rval_t
+SEQUENCE_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_enc_rval_t er;
+        asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
+	asn_TYPE_member_t *elm = td->elements;
+	asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(sptr);
+	const char *mname = specs->as_XMLValueList
+		? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
+	unsigned int mlen = mname ? strlen(mname) : 0;
+	int xcan = (flags & XER_F_CANONICAL);
+	int i;
+
+	if(!sptr) ASN__ENCODE_FAILED;
+
+	er.encoded = 0;
+
+	for(i = 0; i < list->count; i++) {
+		asn_enc_rval_t tmper;
+		void *memb_ptr = list->array[i];
+		if(!memb_ptr) continue;
+
+		if(mname) {
+			if(!xcan) ASN__TEXT_INDENT(1, ilevel);
+			ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
+		}
+
+		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
+				ilevel + 1, flags, cb, app_key);
+		if(tmper.encoded == -1) return tmper;
+                if(tmper.encoded == 0 && specs->as_XMLValueList) {
+                        const char *name = elm->type->xml_tag;
+			size_t len = strlen(name);
+			if(!xcan) ASN__TEXT_INDENT(1, ilevel + 1);
+			ASN__CALLBACK3("<", 1, name, len, "/>", 2);
+                }
+
+		if(mname) {
+			ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);
+			er.encoded += 5;
+		}
+
+		er.encoded += (2 * mlen) + tmper.encoded;
+	}
+
+	if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
+
+	ASN__ENCODED_OK(er);
+cb_failed:
+	ASN__ENCODE_FAILED;
+}
+
+asn_enc_rval_t
+SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+	asn_anonymous_sequence_ *list;
+	asn_per_constraint_t *ct;
+	asn_enc_rval_t er;
+	asn_TYPE_member_t *elm = td->elements;
+	int seq;
+
+	if(!sptr) ASN__ENCODE_FAILED;
+	list = _A_SEQUENCE_FROM_VOID(sptr);
+
+	er.encoded = 0;
+
+	ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count);
+
+	if(constraints) ct = &constraints->size;
+	else if(td->per_constraints) ct = &td->per_constraints->size;
+	else ct = 0;
+
+	/* If extensible constraint, check if size is in root */
+	if(ct) {
+		int not_in_root = (list->count < ct->lower_bound
+				|| list->count > ct->upper_bound);
+		ASN_DEBUG("lb %ld ub %ld %s",
+			ct->lower_bound, ct->upper_bound,
+			ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
+		if(ct->flags & APC_EXTENSIBLE) {
+			/* Declare whether size is in extension root */
+			if(per_put_few_bits(po, not_in_root, 1))
+				ASN__ENCODE_FAILED;
+			if(not_in_root) ct = 0;
+		} else if(not_in_root && ct->effective_bits >= 0)
+			ASN__ENCODE_FAILED;
+	}
+
+	if(ct && ct->effective_bits >= 0) {
+		/* X.691, #19.5: No length determinant */
+		if(per_put_few_bits(po, list->count - ct->lower_bound,
+				ct->effective_bits))
+			ASN__ENCODE_FAILED;
+	}
+
+	for(seq = -1; seq < list->count;) {
+		ssize_t mayEncode;
+		if(seq < 0) seq = 0;
+		if(ct && ct->effective_bits >= 0) {
+			mayEncode = list->count;
+		} else {
+			mayEncode = uper_put_length(po, list->count - seq);
+			if(mayEncode < 0) ASN__ENCODE_FAILED;
+		}
+
+		while(mayEncode--) {
+			void *memb_ptr = list->array[seq++];
+			if(!memb_ptr) ASN__ENCODE_FAILED;
+			er = elm->type->uper_encoder(elm->type,
+				elm->per_constraints, memb_ptr, po);
+			if(er.encoded == -1)
+				ASN__ENCODE_FAILED;
+		}
+	}
+
+	ASN__ENCODED_OK(er);
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h b/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h
new file mode 100644
index 000000000000..e2272f326ba1
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_CONSTR_SEQUENCE_OF_H_
+#define	_CONSTR_SEQUENCE_OF_H_
+
+#include <asn_application.h>
+#include <constr_SET_OF.h>		/* Implemented using SET OF */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * A set specialized functions dealing with the SEQUENCE OF type.
+ * Generally implemented using SET OF.
+ */
+#define	SEQUENCE_OF_free	SET_OF_free
+#define	SEQUENCE_OF_print	SET_OF_print
+#define	SEQUENCE_OF_constraint	SET_OF_constraint
+#define	SEQUENCE_OF_decode_ber	SET_OF_decode_ber
+#define	SEQUENCE_OF_decode_xer	SET_OF_decode_xer
+#define	SEQUENCE_OF_decode_uper	SET_OF_decode_uper
+der_type_encoder_f SEQUENCE_OF_encode_der;
+xer_type_encoder_f SEQUENCE_OF_encode_xer;
+per_type_encoder_f SEQUENCE_OF_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _CONSTR_SET_OF_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/constr_SET_OF.c b/libkmod/pkcs7/asn1c-gen/constr_SET_OF.c
new file mode 100644
index 000000000000..2dbc6e518846
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_SET_OF.c
@@ -0,0 +1,954 @@
+/*-
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_SET_OF.h>
+#include <asn_SET_OF.h>
+
+/*
+ * Number of bytes left for this structure.
+ * (ctx->left) indicates the number of bytes _transferred_ for the structure.
+ * (size) contains the number of bytes in the buffer passed.
+ */
+#define	LEFT	((size<(size_t)ctx->left)?size:(size_t)ctx->left)
+
+/*
+ * If the subprocessor function returns with an indication that it wants
+ * more data, it may well be a fatal decoding problem, because the
+ * size is constrained by the <TLV>'s L, even if the buffer size allows
+ * reading more data.
+ * For example, consider the buffer containing the following TLVs:
+ * <T:5><L:1><V> <T:6>...
+ * The TLV length clearly indicates that one byte is expected in V, but
+ * if the V processor returns with "want more data" even if the buffer
+ * contains way more data than the V processor have seen.
+ */
+#define	SIZE_VIOLATION	(ctx->left >= 0 && (size_t)ctx->left <= size)
+
+/*
+ * This macro "eats" the part of the buffer which is definitely "consumed",
+ * i.e. was correctly converted into local representation or rightfully skipped.
+ */
+#undef	ADVANCE
+#define	ADVANCE(num_bytes)	do {		\
+		size_t num = num_bytes;		\
+		ptr = ((const char *)ptr) + num;\
+		size -= num;			\
+		if(ctx->left >= 0)		\
+			ctx->left -= num;	\
+		consumed_myself += num;		\
+	} while(0)
+
+/*
+ * Switch to the next phase of parsing.
+ */
+#undef	NEXT_PHASE
+#undef	PHASE_OUT
+#define	NEXT_PHASE(ctx)	do {			\
+		ctx->phase++;			\
+		ctx->step = 0;			\
+	} while(0)
+#define	PHASE_OUT(ctx)	do { ctx->phase = 10; } while(0)
+
+/*
+ * Return a standardized complex structure.
+ */
+#undef	RETURN
+#define	RETURN(_code)	do {			\
+		rval.code = _code;		\
+		rval.consumed = consumed_myself;\
+		return rval;			\
+	} while(0)
+
+/*
+ * The decoder of the SET OF type.
+ */
+asn_dec_rval_t
+SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+	void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
+	/*
+	 * Bring closer parts of structure description.
+	 */
+	asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
+	asn_TYPE_member_t *elm = td->elements;	/* Single one */
+
+	/*
+	 * Parts of the structure being constructed.
+	 */
+	void *st = *struct_ptr;	/* Target structure. */
+	asn_struct_ctx_t *ctx;	/* Decoder context */
+
+	ber_tlv_tag_t tlv_tag;	/* T from TLV */
+	asn_dec_rval_t rval;	/* Return code from subparsers */
+
+	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
+
+	ASN_DEBUG("Decoding %s as SET OF", td->name);
+	
+	/*
+	 * Create the target structure if it is not present already.
+	 */
+	if(st == 0) {
+		st = *struct_ptr = CALLOC(1, specs->struct_size);
+		if(st == 0) {
+			RETURN(RC_FAIL);
+		}
+	}
+
+	/*
+	 * Restore parsing context.
+	 */
+	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
+	
+	/*
+	 * Start to parse where left previously
+	 */
+	switch(ctx->phase) {
+	case 0:
+		/*
+		 * PHASE 0.
+		 * Check that the set of tags associated with given structure
+		 * perfectly fits our expectations.
+		 */
+
+		rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
+			tag_mode, 1, &ctx->left, 0);
+		if(rval.code != RC_OK) {
+			ASN_DEBUG("%s tagging check failed: %d",
+				td->name, rval.code);
+			return rval;
+		}
+
+		if(ctx->left >= 0)
+			ctx->left += rval.consumed; /* ?Substracted below! */
+		ADVANCE(rval.consumed);
+
+		ASN_DEBUG("Structure consumes %ld bytes, "
+			"buffer %ld", (long)ctx->left, (long)size);
+
+		NEXT_PHASE(ctx);
+		/* Fall through */
+	case 1:
+		/*
+		 * PHASE 1.
+		 * From the place where we've left it previously,
+		 * try to decode the next item.
+		 */
+	  for(;; ctx->step = 0) {
+		ssize_t tag_len;	/* Length of TLV's T */
+
+		if(ctx->step & 1)
+			goto microphase2;
+
+		/*
+		 * MICROPHASE 1: Synchronize decoding.
+		 */
+
+		if(ctx->left == 0) {
+			ASN_DEBUG("End of SET OF %s", td->name);
+			/*
+			 * No more things to decode.
+			 * Exit out of here.
+			 */
+			PHASE_OUT(ctx);
+			RETURN(RC_OK);
+		}
+
+		/*
+		 * Fetch the T from TLV.
+		 */
+		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
+		switch(tag_len) {
+		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
+			/* Fall through */
+		case -1: RETURN(RC_FAIL);
+		}
+
+		if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
+			if(LEFT < 2) {
+				if(SIZE_VIOLATION)
+					RETURN(RC_FAIL);
+				else
+					RETURN(RC_WMORE);
+			} else if(((const uint8_t *)ptr)[1] == 0) {
+				/*
+				 * Found the terminator of the
+				 * indefinite length structure.
+				 */
+				break;
+			}
+		}
+
+		/* Outmost tag may be unknown and cannot be fetched/compared */
+		if(elm->tag != (ber_tlv_tag_t)-1) {
+		    if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) {
+			/*
+			 * The new list member of expected type has arrived.
+			 */
+		    } else {
+			ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
+				ber_tlv_tag_string(tlv_tag), td->name);
+			ASN_DEBUG("%s SET OF has tag %s",
+				td->name, ber_tlv_tag_string(elm->tag));
+			RETURN(RC_FAIL);
+		    }
+		}
+
+		/*
+		 * MICROPHASE 2: Invoke the member-specific decoder.
+		 */
+		ctx->step |= 1;		/* Confirm entering next microphase */
+	microphase2:
+		
+		/*
+		 * Invoke the member fetch routine according to member's type
+		 */
+		rval = elm->type->ber_decoder(opt_codec_ctx,
+				elm->type, &ctx->ptr, ptr, LEFT, 0);
+		ASN_DEBUG("In %s SET OF %s code %d consumed %d",
+			td->name, elm->type->name,
+			rval.code, (int)rval.consumed);
+		switch(rval.code) {
+		case RC_OK:
+			{
+				asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
+				if(ASN_SET_ADD(list, ctx->ptr) != 0)
+					RETURN(RC_FAIL);
+				else
+					ctx->ptr = 0;
+			}
+			break;
+		case RC_WMORE: /* More data expected */
+			if(!SIZE_VIOLATION) {
+				ADVANCE(rval.consumed);
+				RETURN(RC_WMORE);
+			}
+			/* Fall through */
+		case RC_FAIL: /* Fatal error */
+			ASN_STRUCT_FREE(*elm->type, ctx->ptr);
+			ctx->ptr = 0;
+			RETURN(RC_FAIL);
+		} /* switch(rval) */
+		
+		ADVANCE(rval.consumed);
+	  }	/* for(all list members) */
+
+		NEXT_PHASE(ctx);
+	case 2:
+		/*
+		 * Read in all "end of content" TLVs.
+		 */
+		while(ctx->left < 0) {
+			if(LEFT < 2) {
+				if(LEFT > 0 && ((const char *)ptr)[0] != 0) {
+					/* Unexpected tag */
+					RETURN(RC_FAIL);
+				} else {
+					RETURN(RC_WMORE);
+				}
+			}
+			if(((const char *)ptr)[0] == 0
+			&& ((const char *)ptr)[1] == 0) {
+				ADVANCE(2);
+				ctx->left++;
+			} else {
+				RETURN(RC_FAIL);
+			}
+		}
+
+		PHASE_OUT(ctx);
+	}
+	
+	RETURN(RC_OK);
+}
+
+/*
+ * Internally visible buffer holding a single encoded element.
+ */
+struct _el_buffer {
+	uint8_t *buf;
+	size_t length;
+	size_t size;
+};
+/* Append bytes to the above structure */
+static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) {
+	struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr;
+
+	if(el_buf->length + size > el_buf->size)
+		return -1;
+
+	memcpy(el_buf->buf + el_buf->length, buffer, size);
+
+	el_buf->length += size;
+	return 0;
+}
+static int _el_buf_cmp(const void *ap, const void *bp) {
+	const struct _el_buffer *a = (const struct _el_buffer *)ap;
+	const struct _el_buffer *b = (const struct _el_buffer *)bp;
+	int ret;
+	size_t common_len;
+
+	if(a->length < b->length)
+		common_len = a->length;
+	else
+		common_len = b->length;
+
+	ret = memcmp(a->buf, b->buf, common_len);
+	if(ret == 0) {
+		if(a->length < b->length)
+			ret = -1;
+		else if(a->length > b->length)
+			ret = 1;
+	}
+
+	return ret;
+}
+
+/*
+ * The DER encoder of the SET OF type.
+ */
+asn_enc_rval_t
+SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
+	int tag_mode, ber_tlv_tag_t tag,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_TYPE_member_t *elm = td->elements;
+	asn_TYPE_descriptor_t *elm_type = elm->type;
+	der_type_encoder_f *der_encoder = elm_type->der_encoder;
+	asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
+	size_t computed_size = 0;
+	ssize_t encoding_size = 0;
+	struct _el_buffer *encoded_els;
+	ssize_t eels_count = 0;
+	size_t max_encoded_len = 1;
+	asn_enc_rval_t erval;
+	int ret;
+	int edx;
+
+	ASN_DEBUG("Estimating size for SET OF %s", td->name);
+
+	/*
+	 * Gather the length of the underlying members sequence.
+	 */
+	for(edx = 0; edx < list->count; edx++) {
+		void *memb_ptr = list->array[edx];
+		if(!memb_ptr) continue;
+		erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0);
+		if(erval.encoded == -1)
+			return erval;
+		computed_size += erval.encoded;
+
+		/* Compute maximum encoding's size */
+		if(max_encoded_len < (size_t)erval.encoded)
+			max_encoded_len = erval.encoded;
+	}
+
+	/*
+	 * Encode the TLV for the sequence itself.
+	 */
+	encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,
+		cb, app_key);
+	if(encoding_size == -1) {
+		erval.encoded = -1;
+		erval.failed_type = td;
+		erval.structure_ptr = ptr;
+		return erval;
+	}
+	computed_size += encoding_size;
+
+	if(!cb || list->count == 0) {
+		erval.encoded = computed_size;
+		ASN__ENCODED_OK(erval);
+	}
+
+	/*
+	 * DER mandates dynamic sorting of the SET OF elements
+	 * according to their encodings. Build an array of the
+	 * encoded elements.
+	 */
+	encoded_els = (struct _el_buffer *)MALLOC(
+				list->count * sizeof(encoded_els[0]));
+	if(encoded_els == NULL) {
+		erval.encoded = -1;
+		erval.failed_type = td;
+		erval.structure_ptr = ptr;
+		return erval;
+	}
+
+	ASN_DEBUG("Encoding members of %s SET OF", td->name);
+
+	/*
+	 * Encode all members.
+	 */
+	for(edx = 0; edx < list->count; edx++) {
+		void *memb_ptr = list->array[edx];
+		struct _el_buffer *encoded_el = &encoded_els[eels_count];
+
+		if(!memb_ptr) continue;
+
+		/*
+		 * Prepare space for encoding.
+		 */
+		encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len);
+		if(encoded_el->buf) {
+			encoded_el->length = 0;
+			encoded_el->size = max_encoded_len;
+		} else {
+			for(edx--; edx >= 0; edx--)
+				FREEMEM(encoded_els[edx].buf);
+			FREEMEM(encoded_els);
+			erval.encoded = -1;
+			erval.failed_type = td;
+			erval.structure_ptr = ptr;
+			return erval;
+		}
+
+		/*
+		 * Encode the member into the prepared space.
+		 */
+		erval = der_encoder(elm_type, memb_ptr, 0, elm->tag,
+			_el_addbytes, encoded_el);
+		if(erval.encoded == -1) {
+			for(; edx >= 0; edx--)
+				FREEMEM(encoded_els[edx].buf);
+			FREEMEM(encoded_els);
+			return erval;
+		}
+		encoding_size += erval.encoded;
+		eels_count++;
+	}
+
+	/*
+	 * Sort the encoded elements according to their encoding.
+	 */
+	qsort(encoded_els, eels_count, sizeof(encoded_els[0]), _el_buf_cmp);
+
+	/*
+	 * Report encoded elements to the application.
+	 * Dispose of temporary sorted members table.
+	 */
+	ret = 0;
+	for(edx = 0; edx < eels_count; edx++) {
+		struct _el_buffer *encoded_el = &encoded_els[edx];
+		/* Report encoded chunks to the application */
+		if(ret == 0
+		&& cb(encoded_el->buf, encoded_el->length, app_key) < 0)
+			ret = -1;
+		FREEMEM(encoded_el->buf);
+	}
+	FREEMEM(encoded_els);
+
+	if(ret || computed_size != (size_t)encoding_size) {
+		/*
+		 * Standard callback failed, or
+		 * encoded size is not equal to the computed size.
+		 */
+		erval.encoded = -1;
+		erval.failed_type = td;
+		erval.structure_ptr = ptr;
+	} else {
+		erval.encoded = computed_size;
+	}
+
+	ASN__ENCODED_OK(erval);
+}
+
+#undef	XER_ADVANCE
+#define	XER_ADVANCE(num_bytes)	do {			\
+		size_t num = num_bytes;			\
+		buf_ptr = ((const char *)buf_ptr) + num;\
+		size -= num;				\
+		consumed_myself += num;			\
+	} while(0)
+
+/*
+ * Decode the XER (XML) data.
+ */
+asn_dec_rval_t
+SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+	void **struct_ptr, const char *opt_mname,
+		const void *buf_ptr, size_t size) {
+	/*
+	 * Bring closer parts of structure description.
+	 */
+	asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
+	asn_TYPE_member_t *element = td->elements;
+	const char *elm_tag;
+	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
+
+	/*
+	 * ... and parts of the structure being constructed.
+	 */
+	void *st = *struct_ptr;	/* Target structure. */
+	asn_struct_ctx_t *ctx;	/* Decoder context */
+
+	asn_dec_rval_t rval;		/* Return value from a decoder */
+	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
+
+	/*
+	 * Create the target structure if it is not present already.
+	 */
+	if(st == 0) {
+		st = *struct_ptr = CALLOC(1, specs->struct_size);
+		if(st == 0) RETURN(RC_FAIL);
+	}
+
+	/* Which tag is expected for the downstream */
+	if(specs->as_XMLValueList) {
+		elm_tag = (specs->as_XMLValueList == 1) ? 0 : "";
+	} else {
+		elm_tag = (*element->name)
+				? element->name : element->type->xml_tag;
+	}
+
+	/*
+	 * Restore parsing context.
+	 */
+	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
+
+	/*
+	 * Phases of XER/XML processing:
+	 * Phase 0: Check that the opening tag matches our expectations.
+	 * Phase 1: Processing body and reacting on closing tag.
+	 * Phase 2: Processing inner type.
+	 */
+	for(; ctx->phase <= 2;) {
+		pxer_chunk_type_e ch_type;	/* XER chunk type */
+		ssize_t ch_size;		/* Chunk size */
+		xer_check_tag_e tcv;		/* Tag check value */
+
+		/*
+		 * Go inside the inner member of a set.
+		 */
+		if(ctx->phase == 2) {
+			asn_dec_rval_t tmprval;
+
+			/* Invoke the inner type decoder, m.b. multiple times */
+			ASN_DEBUG("XER/SET OF element [%s]", elm_tag);
+			tmprval = element->type->xer_decoder(opt_codec_ctx,
+					element->type, &ctx->ptr, elm_tag,
+					buf_ptr, size);
+			if(tmprval.code == RC_OK) {
+				asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
+				if(ASN_SET_ADD(list, ctx->ptr) != 0)
+					RETURN(RC_FAIL);
+				ctx->ptr = 0;
+				XER_ADVANCE(tmprval.consumed);
+			} else {
+				XER_ADVANCE(tmprval.consumed);
+				RETURN(tmprval.code);
+			}
+			ctx->phase = 1;	/* Back to body processing */
+			ASN_DEBUG("XER/SET OF phase => %d", ctx->phase);
+			/* Fall through */
+		}
+
+		/*
+		 * Get the next part of the XML stream.
+		 */
+		ch_size = xer_next_token(&ctx->context,
+			buf_ptr, size, &ch_type);
+		if(ch_size == -1) {
+            RETURN(RC_FAIL);
+        } else {
+			switch(ch_type) {
+            case PXER_WMORE:
+                RETURN(RC_WMORE);
+			case PXER_COMMENT:	/* Got XML comment */
+			case PXER_TEXT:		/* Ignore free-standing text */
+				XER_ADVANCE(ch_size);	/* Skip silently */
+				continue;
+			case PXER_TAG:
+				break;	/* Check the rest down there */
+			}
+		}
+
+		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
+		ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s",
+			tcv, ctx->phase, xml_tag);
+		switch(tcv) {
+		case XCT_CLOSING:
+			if(ctx->phase == 0) break;
+			ctx->phase = 0;
+			/* Fall through */
+		case XCT_BOTH:
+			if(ctx->phase == 0) {
+				/* No more things to decode */
+				XER_ADVANCE(ch_size);
+				ctx->phase = 3;	/* Phase out */
+				RETURN(RC_OK);
+			}
+			/* Fall through */
+		case XCT_OPENING:
+			if(ctx->phase == 0) {
+				XER_ADVANCE(ch_size);
+				ctx->phase = 1;	/* Processing body phase */
+				continue;
+			}
+			/* Fall through */
+		case XCT_UNKNOWN_OP:
+		case XCT_UNKNOWN_BO:
+
+			ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase);
+			if(ctx->phase == 1) {
+				/*
+				 * Process a single possible member.
+				 */
+				ctx->phase = 2;
+				continue;
+			}
+			/* Fall through */
+		default:
+			break;
+		}
+
+		ASN_DEBUG("Unexpected XML tag in SET OF");
+		break;
+	}
+
+	ctx->phase = 3;	/* "Phase out" on hard failure */
+	RETURN(RC_FAIL);
+}
+
+
+
+typedef struct xer_tmp_enc_s {
+	void *buffer;
+	size_t offset;
+	size_t size;
+} xer_tmp_enc_t;
+static int
+SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) {
+	xer_tmp_enc_t *t = (xer_tmp_enc_t *)key;
+	if(t->offset + size >= t->size) {
+		size_t newsize = (t->size << 2) + size;
+		void *p = REALLOC(t->buffer, newsize);
+		if(!p) return -1;
+		t->buffer = p;
+		t->size = newsize;
+	}
+	memcpy((char *)t->buffer + t->offset, buffer, size);
+	t->offset += size;
+	return 0;
+}
+static int
+SET_OF_xer_order(const void *aptr, const void *bptr) {
+	const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr;
+	const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr;
+	size_t minlen = a->offset;
+	int ret;
+	if(b->offset < minlen) minlen = b->offset;
+	/* Well-formed UTF-8 has this nice lexicographical property... */
+	ret = memcmp(a->buffer, b->buffer, minlen);
+	if(ret != 0) return ret;
+	if(a->offset == b->offset)
+		return 0;
+	if(a->offset == minlen)
+		return -1;
+	return 1;
+}
+
+
+asn_enc_rval_t
+SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+	int ilevel, enum xer_encoder_flags_e flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_enc_rval_t er;
+	asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
+	asn_TYPE_member_t *elm = td->elements;
+	asn_anonymous_set_ *list = _A_SET_FROM_VOID(sptr);
+	const char *mname = specs->as_XMLValueList
+		? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
+	size_t mlen = mname ? strlen(mname) : 0;
+	int xcan = (flags & XER_F_CANONICAL);
+	xer_tmp_enc_t *encs = 0;
+	size_t encs_count = 0;
+	void *original_app_key = app_key;
+	asn_app_consume_bytes_f *original_cb = cb;
+	int i;
+
+	if(!sptr) ASN__ENCODE_FAILED;
+
+	if(xcan) {
+		encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0]));
+		if(!encs) ASN__ENCODE_FAILED;
+		cb = SET_OF_encode_xer_callback;
+	}
+
+	er.encoded = 0;
+
+	for(i = 0; i < list->count; i++) {
+		asn_enc_rval_t tmper;
+
+		void *memb_ptr = list->array[i];
+		if(!memb_ptr) continue;
+
+		if(encs) {
+			memset(&encs[encs_count], 0, sizeof(encs[0]));
+			app_key = &encs[encs_count];
+			encs_count++;
+		}
+
+		if(mname) {
+			if(!xcan) ASN__TEXT_INDENT(1, ilevel);
+			ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
+		}
+
+		if(!xcan && specs->as_XMLValueList == 1)
+			ASN__TEXT_INDENT(1, ilevel + 1);
+		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
+				ilevel + (specs->as_XMLValueList != 2),
+				flags, cb, app_key);
+		if(tmper.encoded == -1) {
+			td = tmper.failed_type;
+			sptr = tmper.structure_ptr;
+			goto cb_failed;
+		}
+		if(tmper.encoded == 0 && specs->as_XMLValueList) {
+			const char *name = elm->type->xml_tag;
+			size_t len = strlen(name);
+			ASN__CALLBACK3("<", 1, name, len, "/>", 2);
+		}
+
+		if(mname) {
+			ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);
+			er.encoded += 5;
+		}
+
+		er.encoded += (2 * mlen) + tmper.encoded;
+	}
+
+	if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
+
+	if(encs) {
+		xer_tmp_enc_t *enc = encs;
+		xer_tmp_enc_t *end = encs + encs_count;
+		ssize_t control_size = 0;
+
+		cb = original_cb;
+		app_key = original_app_key;
+		qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order);
+
+		for(; enc < end; enc++) {
+			ASN__CALLBACK(enc->buffer, enc->offset);
+			FREEMEM(enc->buffer);
+			enc->buffer = 0;
+			control_size += enc->offset;
+		}
+		assert(control_size == er.encoded);
+	}
+
+	goto cleanup;
+cb_failed:
+	er.encoded = -1;
+	er.failed_type = td;
+	er.structure_ptr = sptr;
+cleanup:
+	if(encs) {
+		while(encs_count-- > 0) {
+			if(encs[encs_count].buffer)
+				FREEMEM(encs[encs_count].buffer);
+		}
+		FREEMEM(encs);
+	}
+	ASN__ENCODED_OK(er);
+}
+
+int
+SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_TYPE_member_t *elm = td->elements;
+	const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
+	int ret;
+	int i;
+
+	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+
+	/* Dump preamble */
+	if(cb(td->name, strlen(td->name), app_key) < 0
+	|| cb(" ::= {", 6, app_key) < 0)
+		return -1;
+
+	for(i = 0; i < list->count; i++) {
+		const void *memb_ptr = list->array[i];
+		if(!memb_ptr) continue;
+
+		_i_INDENT(1);
+
+		ret = elm->type->print_struct(elm->type, memb_ptr,
+			ilevel + 1, cb, app_key);
+		if(ret) return ret;
+	}
+
+	ilevel--;
+	_i_INDENT(1);
+
+	return (cb("}", 1, app_key) < 0) ? -1 : 0;
+}
+
+void
+SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
+	if(td && ptr) {
+		asn_SET_OF_specifics_t *specs;
+		asn_TYPE_member_t *elm = td->elements;
+		asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
+		asn_struct_ctx_t *ctx;	/* Decoder context */
+		int i;
+
+		/*
+		 * Could not use set_of_empty() because of (*free)
+		 * incompatibility.
+		 */
+		for(i = 0; i < list->count; i++) {
+			void *memb_ptr = list->array[i];
+			if(memb_ptr)
+			ASN_STRUCT_FREE(*elm->type, memb_ptr);
+		}
+		list->count = 0;	/* No meaningful elements left */
+
+		asn_set_empty(list);	/* Remove (list->array) */
+
+		specs = (asn_SET_OF_specifics_t *)td->specifics;
+		ctx = (asn_struct_ctx_t *)((char *)ptr + specs->ctx_offset);
+		if(ctx->ptr) {
+			ASN_STRUCT_FREE(*elm->type, ctx->ptr);
+			ctx->ptr = 0;
+		}
+
+		if(!contents_only) {
+			FREEMEM(ptr);
+		}
+	}
+}
+
+int
+SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	asn_TYPE_member_t *elm = td->elements;
+	asn_constr_check_f *constr;
+	const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
+	int i;
+
+	if(!sptr) {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: value not given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+
+	constr = elm->memb_constraints;
+	if(!constr) constr = elm->type->check_constraints;
+
+	/*
+	 * Iterate over the members of an array.
+	 * Validate each in turn, until one fails.
+	 */
+	for(i = 0; i < list->count; i++) {
+		const void *memb_ptr = list->array[i];
+		int ret;
+
+		if(!memb_ptr) continue;
+
+		ret = constr(elm->type, memb_ptr, ctfailcb, app_key);
+		if(ret) return ret;
+	}
+
+	/*
+	 * Cannot inherit it eralier:
+	 * need to make sure we get the updated version.
+	 */
+	if(!elm->memb_constraints)
+		elm->memb_constraints = elm->type->check_constraints;
+
+	return 0;
+}
+
+asn_dec_rval_t
+SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+        asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+	asn_dec_rval_t rv;
+        asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
+	asn_TYPE_member_t *elm = td->elements;	/* Single one */
+	void *st = *sptr;
+	asn_anonymous_set_ *list;
+	asn_per_constraint_t *ct;
+	int repeat = 0;
+	ssize_t nelems;
+
+	if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
+		ASN__DECODE_FAILED;
+
+	/*
+	 * Create the target structure if it is not present already.
+	 */
+	if(!st) {
+		st = *sptr = CALLOC(1, specs->struct_size);
+		if(!st) ASN__DECODE_FAILED;
+	}                                                                       
+	list = _A_SET_FROM_VOID(st);
+
+	/* Figure out which constraints to use */
+	if(constraints) ct = &constraints->size;
+	else if(td->per_constraints) ct = &td->per_constraints->size;
+	else ct = 0;
+
+	if(ct && ct->flags & APC_EXTENSIBLE) {
+		int value = per_get_few_bits(pd, 1);
+		if(value < 0) ASN__DECODE_STARVED;
+		if(value) ct = 0;	/* Not restricted! */
+	}
+
+	if(ct && ct->effective_bits >= 0) {
+		/* X.691, #19.5: No length determinant */
+		nelems = per_get_few_bits(pd, ct->effective_bits);
+		ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
+			(long)nelems, ct->lower_bound, td->name);
+		if(nelems < 0)  ASN__DECODE_STARVED;
+		nelems += ct->lower_bound;
+	} else {
+		nelems = -1;
+	}
+
+	do {
+		int i;
+		if(nelems < 0) {
+			nelems = uper_get_length(pd,
+				ct ? ct->effective_bits : -1, &repeat);
+			ASN_DEBUG("Got to decode %d elements (eff %d)",
+				(int)nelems, (int)(ct ? ct->effective_bits : -1));
+			if(nelems < 0) ASN__DECODE_STARVED;
+		}
+
+		for(i = 0; i < nelems; i++) {
+			void *ptr = 0;
+			ASN_DEBUG("SET OF %s decoding", elm->type->name);
+			rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
+				elm->per_constraints, &ptr, pd);
+			ASN_DEBUG("%s SET OF %s decoded %d, %p",
+				td->name, elm->type->name, rv.code, ptr);
+			if(rv.code == RC_OK) {
+				if(ASN_SET_ADD(list, ptr) == 0)
+					continue;
+				ASN_DEBUG("Failed to add element into %s",
+					td->name);
+				/* Fall through */
+				rv.code = RC_FAIL;
+			} else {
+				ASN_DEBUG("Failed decoding %s of %s (SET OF)",
+					elm->type->name, td->name);
+			}
+			if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
+			return rv;
+		}
+
+		nelems = -1;	/* Allow uper_get_length() */
+	} while(repeat);
+
+	ASN_DEBUG("Decoded %s as SET OF", td->name);
+
+	rv.code = RC_OK;
+	rv.consumed = 0;
+	return rv;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/constr_SET_OF.h b/libkmod/pkcs7/asn1c-gen/constr_SET_OF.h
new file mode 100644
index 000000000000..75e18cfa0c5f
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_SET_OF.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_CONSTR_SET_OF_H_
+#define	_CONSTR_SET_OF_H_
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef const struct asn_SET_OF_specifics_s {
+	/*
+	 * Target structure description.
+	 */
+	int struct_size;	/* Size of the target structure. */
+	int ctx_offset;		/* Offset of the asn_struct_ctx_t member */
+
+	/* XER-specific stuff */
+	int as_XMLValueList;	/* The member type must be encoded like this */
+} asn_SET_OF_specifics_t;
+
+/*
+ * A set specialized functions dealing with the SET OF type.
+ */
+asn_struct_free_f SET_OF_free;
+asn_struct_print_f SET_OF_print;
+asn_constr_check_f SET_OF_constraint;
+ber_type_decoder_f SET_OF_decode_ber;
+der_type_encoder_f SET_OF_encode_der;
+xer_type_decoder_f SET_OF_decode_xer;
+xer_type_encoder_f SET_OF_encode_xer;
+per_type_decoder_f SET_OF_decode_uper;
+per_type_encoder_f SET_OF_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _CONSTR_SET_OF_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/constr_TYPE.c b/libkmod/pkcs7/asn1c-gen/constr_TYPE.c
new file mode 100644
index 000000000000..322f68c86c8b
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_TYPE.c
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <constr_TYPE.h>
+#include <errno.h>
+
+/*
+ * Version of the ASN.1 infrastructure shipped with compiler.
+ */
+int get_asn1c_environment_version() { return ASN1C_ENVIRONMENT_VERSION; }
+
+static asn_app_consume_bytes_f _print2fp;
+
+/*
+ * Return the outmost tag of the type.
+ */
+ber_tlv_tag_t
+asn_TYPE_outmost_tag(const asn_TYPE_descriptor_t *type_descriptor,
+		const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag) {
+
+	if(tag_mode)
+		return tag;
+
+	if(type_descriptor->tags_count)
+		return type_descriptor->tags[0];
+
+	return type_descriptor->outmost_tag(type_descriptor, struct_ptr, 0, 0);
+}
+
+/*
+ * Print the target language's structure in human readable form.
+ */
+int
+asn_fprint(FILE *stream, asn_TYPE_descriptor_t *td, const void *struct_ptr) {
+	if(!stream) stream = stdout;
+	if(!td || !struct_ptr) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Invoke type-specific printer */
+	if(td->print_struct(td, struct_ptr, 1, _print2fp, stream))
+		return -1;
+
+	/* Terminate the output */
+	if(_print2fp("\n", 1, stream))
+		return -1;
+
+	return fflush(stream);
+}
+
+/* Dump the data into the specified stdio stream */
+static int
+_print2fp(const void *buffer, size_t size, void *app_key) {
+	FILE *stream = (FILE *)app_key;
+
+	if(fwrite(buffer, 1, size, stream) != size)
+		return -1;
+
+	return 0;
+}
+
+
+/*
+ * Some compilers do not support variable args macros.
+ * This function is a replacement of ASN_DEBUG() macro.
+ */
+void ASN_DEBUG_f(const char *fmt, ...);
+void ASN_DEBUG_f(const char *fmt, ...) {
+	va_list ap;
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+}
diff --git a/libkmod/pkcs7/asn1c-gen/constr_TYPE.h b/libkmod/pkcs7/asn1c-gen/constr_TYPE.h
new file mode 100644
index 000000000000..a9cd86dc3d65
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constr_TYPE.h
@@ -0,0 +1,180 @@
+/*-
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+/*
+ * This file contains the declaration structure called "ASN.1 Type Definition",
+ * which holds all information necessary for encoding and decoding routines.
+ * This structure even contains pointer to these encoding and decoding routines
+ * for each defined ASN.1 type.
+ */
+#ifndef	_CONSTR_TYPE_H_
+#define	_CONSTR_TYPE_H_
+
+#include <ber_tlv_length.h>
+#include <ber_tlv_tag.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;	/* Forward declaration */
+struct asn_TYPE_member_s;	/* Forward declaration */
+
+/*
+ * This type provides the context information for various ASN.1 routines,
+ * primarily ones doing decoding. A member _asn_ctx of this type must be
+ * included into certain target language's structures, such as compound types.
+ */
+typedef struct asn_struct_ctx_s {
+	short phase;		/* Decoding phase */
+	short step;		/* Elementary step of a phase */
+	int context;		/* Other context information */
+	void *ptr;		/* Decoder-specific stuff (stack elements) */
+	ber_tlv_len_t left;	/* Number of bytes left, -1 for indefinite */
+} asn_struct_ctx_t;
+
+#include <ber_decoder.h>	/* Basic Encoding Rules decoder */
+#include <der_encoder.h>	/* Distinguished Encoding Rules encoder */
+#include <xer_decoder.h>	/* Decoder of XER (XML, text) */
+#include <xer_encoder.h>	/* Encoder into XER (XML, text) */
+#include <per_decoder.h>	/* Packet Encoding Rules decoder */
+#include <per_encoder.h>	/* Packet Encoding Rules encoder */
+#include <constraints.h>	/* Subtype constraints support */
+
+/*
+ * Free the structure according to its specification.
+ * If (free_contents_only) is set, the wrapper structure itself (struct_ptr)
+ * will not be freed. (It may be useful in case the structure is allocated
+ * statically or arranged on the stack, yet its elements are allocated
+ * dynamically.)
+ */
+typedef void (asn_struct_free_f)(
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		void *struct_ptr, int free_contents_only);
+#define	ASN_STRUCT_FREE(asn_DEF, ptr)	(asn_DEF).free_struct(&(asn_DEF),ptr,0)
+#define	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr)	\
+					(asn_DEF).free_struct(&(asn_DEF),ptr,1)
+
+/*
+ * Print the structure according to its specification.
+ */
+typedef int (asn_struct_print_f)(
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		const void *struct_ptr,
+		int level,	/* Indentation level */
+		asn_app_consume_bytes_f *callback, void *app_key);
+
+/*
+ * Return the outmost tag of the type.
+ * If the type is untagged CHOICE, the dynamic operation is performed.
+ * NOTE: This function pointer type is only useful internally.
+ * Do not use it in your application.
+ */
+typedef ber_tlv_tag_t (asn_outmost_tag_f)(
+		const struct asn_TYPE_descriptor_s *type_descriptor,
+		const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag);
+/* The instance of the above function type; used internally. */
+asn_outmost_tag_f asn_TYPE_outmost_tag;
+
+\f
+/*
+ * The definitive description of the destination language's structure.
+ */
+typedef struct asn_TYPE_descriptor_s {
+	const char *name;	/* A name of the ASN.1 type. "" in some cases. */
+	const char *xml_tag;	/* Name used in XML tag */
+
+	/*
+	 * Generalized functions for dealing with the specific type.
+	 * May be directly invoked by applications.
+	 */
+	asn_struct_free_f  *free_struct;	/* Free the structure */
+	asn_struct_print_f *print_struct;	/* Human readable output */
+	asn_constr_check_f *check_constraints;	/* Constraints validator */
+	ber_type_decoder_f *ber_decoder;	/* Generic BER decoder */
+	der_type_encoder_f *der_encoder;	/* Canonical DER encoder */
+	xer_type_decoder_f *xer_decoder;	/* Generic XER decoder */
+	xer_type_encoder_f *xer_encoder;	/* [Canonical] XER encoder */
+	per_type_decoder_f *uper_decoder;	/* Unaligned PER decoder */
+	per_type_encoder_f *uper_encoder;	/* Unaligned PER encoder */
+
+	/***********************************************************************
+	 * Internally useful members. Not to be used by applications directly. *
+	 **********************************************************************/
+
+	/*
+	 * Tags that are expected to occur.
+	 */
+	asn_outmost_tag_f  *outmost_tag;	/* <optional, internal> */
+	const ber_tlv_tag_t *tags;	/* Effective tags sequence for this type */
+	int tags_count;			/* Number of tags which are expected */
+	const ber_tlv_tag_t *all_tags;	/* Every tag for BER/containment */
+	int all_tags_count;		/* Number of tags */
+
+	asn_per_constraints_t *per_constraints;	/* PER compiled constraints */
+
+	/*
+	 * An ASN.1 production type members (members of SEQUENCE, SET, CHOICE).
+	 */
+	struct asn_TYPE_member_s *elements;
+	int elements_count;
+
+	/*
+	 * Additional information describing the type, used by appropriate
+	 * functions above.
+	 */
+	const void *specifics;
+} asn_TYPE_descriptor_t;
+
+/*
+ * This type describes an element of the constructed type,
+ * i.e. SEQUENCE, SET, CHOICE, etc.
+ */
+  enum asn_TYPE_flags_e {
+	ATF_NOFLAGS,
+	ATF_POINTER	= 0x01,	/* Represented by the pointer */
+	ATF_OPEN_TYPE	= 0x02	/* ANY type, without meaningful tag */
+  };
+typedef struct asn_TYPE_member_s {
+	enum asn_TYPE_flags_e flags;	/* Element's presentation flags */
+	int optional;	/* Following optional members, including current */
+	int memb_offset;		/* Offset of the element */
+	ber_tlv_tag_t tag;		/* Outmost (most immediate) tag */
+	int tag_mode;		/* IMPLICIT/no/EXPLICIT tag at current level */
+	asn_TYPE_descriptor_t *type;	/* Member type descriptor */
+	asn_constr_check_f *memb_constraints;	/* Constraints validator */
+	asn_per_constraints_t *per_constraints;	/* PER compiled constraints */
+	int (*default_value)(int setval, void **sptr);	/* DEFAULT <value> */
+	const char *name;			/* ASN.1 identifier of the element */
+} asn_TYPE_member_t;
+
+/*
+ * BER tag to element number mapping.
+ */
+typedef struct asn_TYPE_tag2member_s {
+	ber_tlv_tag_t el_tag;	/* Outmost tag of the member */
+	int el_no;		/* Index of the associated member, base 0 */
+	int toff_first;		/* First occurence of the el_tag, relative */
+	int toff_last;		/* Last occurence of the el_tag, relatvie */
+} asn_TYPE_tag2member_t;
+
+/*
+ * This function is a wrapper around (td)->print_struct, which prints out
+ * the contents of the target language's structure (struct_ptr) into the
+ * file pointer (stream) in human readable form.
+ * RETURN VALUES:
+ * 	 0: The structure is printed.
+ * 	-1: Problem dumping the structure.
+ * (See also xer_fprint() in xer_encoder.h)
+ */
+int asn_fprint(FILE *stream,		/* Destination stream descriptor */
+	asn_TYPE_descriptor_t *td,	/* ASN.1 type descriptor */
+	const void *struct_ptr);	/* Structure to be printed */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _CONSTR_TYPE_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/constraints.c b/libkmod/pkcs7/asn1c-gen/constraints.c
new file mode 100644
index 000000000000..1bdda73e5d68
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constraints.c
@@ -0,0 +1,93 @@
+#include "asn_internal.h"
+#include "constraints.h"
+
+int
+asn_generic_no_constraint(asn_TYPE_descriptor_t *type_descriptor,
+	const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) {
+
+	(void)type_descriptor;	/* Unused argument */
+	(void)struct_ptr;	/* Unused argument */
+	(void)cb;	/* Unused argument */
+	(void)key;	/* Unused argument */
+
+	/* Nothing to check */
+	return 0;
+}
+
+int
+asn_generic_unknown_constraint(asn_TYPE_descriptor_t *type_descriptor,
+	const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) {
+
+	(void)type_descriptor;	/* Unused argument */
+	(void)struct_ptr;	/* Unused argument */
+	(void)cb;	/* Unused argument */
+	(void)key;	/* Unused argument */
+
+	/* Unknown how to check */
+	return 0;
+}
+
+struct errbufDesc {
+	asn_TYPE_descriptor_t *failed_type;
+	const void *failed_struct_ptr;
+	char *errbuf;
+	size_t errlen;
+};
+
+static void
+_asn_i_ctfailcb(void *key, asn_TYPE_descriptor_t *td, const void *sptr, const char *fmt, ...) {
+	struct errbufDesc *arg = key;
+	va_list ap;
+	ssize_t vlen;
+	ssize_t maxlen;
+
+	arg->failed_type = td;
+	arg->failed_struct_ptr = sptr;
+
+	maxlen = arg->errlen;
+	if(maxlen <= 0)
+		return;
+
+	va_start(ap, fmt);
+	vlen = vsnprintf(arg->errbuf, maxlen, fmt, ap);
+	va_end(ap);
+	if(vlen >= maxlen) {
+		arg->errbuf[maxlen-1] = '\0';	/* Ensuring libc correctness */
+		arg->errlen = maxlen - 1;	/* Not counting termination */
+		return;
+	} else if(vlen >= 0) {
+		arg->errbuf[vlen] = '\0';	/* Ensuring libc correctness */
+		arg->errlen = vlen;		/* Not counting termination */
+	} else {
+		/*
+		 * The libc on this system is broken.
+		 */
+		vlen = sizeof("<broken vsnprintf>") - 1;
+		maxlen--;
+		arg->errlen = vlen < maxlen ? vlen : maxlen;
+		memcpy(arg->errbuf, "<broken vsnprintf>", arg->errlen);
+		arg->errbuf[arg->errlen] = 0;
+	}
+
+	return;
+}
+
+int
+asn_check_constraints(asn_TYPE_descriptor_t *type_descriptor,
+		const void *struct_ptr, char *errbuf, size_t *errlen) {
+	struct errbufDesc arg;
+	int ret;
+
+	arg.failed_type = 0;
+	arg.failed_struct_ptr = 0;
+	arg.errbuf = errbuf;
+	arg.errlen = errlen ? *errlen : 0;
+
+	ret = type_descriptor->check_constraints(type_descriptor,
+		struct_ptr, _asn_i_ctfailcb, &arg);
+	if(ret == -1 && errlen)
+		*errlen = arg.errlen;
+
+	return ret;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/constraints.h b/libkmod/pkcs7/asn1c-gen/constraints.h
new file mode 100644
index 000000000000..48d49e246a3f
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/constraints.h
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	ASN1_CONSTRAINTS_VALIDATOR_H
+#define	ASN1_CONSTRAINTS_VALIDATOR_H
+
+#include <asn_system.h>		/* Platform-dependent types */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;		/* Forward declaration */
+
+/*
+ * Validate the structure according to the ASN.1 constraints.
+ * If errbuf and errlen are given, they shall be pointing to the appropriate
+ * buffer space and its length before calling this function. Alternatively,
+ * they could be passed as NULL's. If constraints validation fails,
+ * errlen will contain the actual number of bytes taken from the errbuf
+ * to encode an error message (properly 0-terminated).
+ * 
+ * RETURN VALUES:
+ * This function returns 0 in case all ASN.1 constraints are met
+ * and -1 if one or more constraints were failed.
+ */
+int
+asn_check_constraints(struct asn_TYPE_descriptor_s *type_descriptor,
+	const void *struct_ptr,	/* Target language's structure */
+	char *errbuf,		/* Returned error description */
+	size_t *errlen		/* Length of the error description */
+	);
+
+
+/*
+ * Generic type for constraint checking callback,
+ * associated with every type descriptor.
+ */
+typedef int (asn_constr_check_f)(
+	struct asn_TYPE_descriptor_s *type_descriptor,
+	const void *struct_ptr,
+	asn_app_constraint_failed_f *optional_callback,	/* Log the error */
+	void *optional_app_key		/* Opaque key passed to a callback */
+	);
+
+/*******************************
+ * INTERNALLY USEFUL FUNCTIONS *
+ *******************************/
+
+asn_constr_check_f asn_generic_no_constraint;	/* No constraint whatsoever */
+asn_constr_check_f asn_generic_unknown_constraint; /* Not fully supported */
+
+/*
+ * Invoke the callback with a complete error message.
+ */
+#define	ASN__CTFAIL	if(ctfailcb) ctfailcb
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ASN1_CONSTRAINTS_VALIDATOR_H */
diff --git a/libkmod/pkcs7/asn1c-gen/converter-sample.c b/libkmod/pkcs7/asn1c-gen/converter-sample.c
new file mode 100644
index 000000000000..de42326d1932
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/converter-sample.c
@@ -0,0 +1,834 @@
+/*
+ * Generic converter template for a selected ASN.1 type.
+ * Copyright (c) 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * 
+ * To compile with your own ASN.1 type, please redefine the PDU as shown:
+ * 
+ * cc -DPDU=MyCustomType -o myDecoder.o -c converter-sample.c
+ */
+#ifdef	HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>	/* for atoi(3) */
+#include <unistd.h>	/* for getopt(3) */
+#include <string.h>	/* for strerror(3) */
+#include <sysexits.h>	/* for EX_* exit codes */
+#include <errno.h>	/* for errno */
+
+#include <asn_application.h>
+#include <asn_internal.h>	/* for ASN__DEFAULT_STACK_MAX */
+
+/* Convert "Type" defined by -DPDU into "asn_DEF_Type" */
+#define	ASN_DEF_PDU(t)	asn_DEF_ ## t
+#define	DEF_PDU_Type(t)	ASN_DEF_PDU(t)
+#define	PDU_Type	DEF_PDU_Type(PDU)
+
+extern asn_TYPE_descriptor_t PDU_Type;	/* ASN.1 type to be decoded */
+#ifdef	ASN_PDU_COLLECTION		/* Generated by asn1c: -pdu=... */
+extern asn_TYPE_descriptor_t *asn_pdu_collection[];
+#endif
+
+/*
+ * Open file and parse its contens.
+ */
+static void *data_decode_from_file(asn_TYPE_descriptor_t *asnTypeOfPDU,
+	FILE *file, const char *name, ssize_t suggested_bufsize, int first_pdu);
+static int write_out(const void *buffer, size_t size, void *key);
+static FILE *argument_to_file(char *av[], int idx);
+static char *argument_to_name(char *av[], int idx);
+
+       int opt_debug;	/* -d (or -dd) */
+static int opt_check;	/* -c (constraints checking) */
+static int opt_stack;	/* -s (maximum stack size) */
+static int opt_nopad;	/* -per-nopad (PER input is not padded) */
+static int opt_onepdu;	/* -1 (decode single PDU) */
+
+/* Input data format selector */
+static enum input_format {
+	INP_BER,	/* -iber: BER input */
+	INP_XER,	/* -ixer: XER input */
+	INP_PER		/* -iper: Unaligned PER input */
+} iform;	/* -i<format> */
+
+/* Output data format selector */
+static enum output_format {
+	OUT_XER,	/* -oxer: XER (XML) output */
+	OUT_DER,	/* -oder: DER (BER) output */
+	OUT_PER,	/* -oper: Unaligned PER output */
+	OUT_TEXT,	/* -otext: semi-structured text */
+	OUT_NULL	/* -onull: No pretty-printing */
+} oform;	/* -o<format> */
+
+#ifdef	JUNKTEST		/* Enable -J <probability> */
+#define	JUNKOPT	"J:"
+static double opt_jprob;	/* Junk bit probability */
+static int    junk_failures;
+static void   junk_bytes_with_probability(uint8_t *, size_t, double prob);
+#else
+#define	JUNKOPT
+#endif
+
+/* Debug output function */
+static inline void
+DEBUG(const char *fmt, ...) {
+	va_list ap;
+	if(!opt_debug) return;
+	fprintf(stderr, "AD: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+}
+
+int
+main(int ac, char *av[]) {
+	static asn_TYPE_descriptor_t *pduType = &PDU_Type;
+	ssize_t suggested_bufsize = 8192;  /* close or equal to stdio buffer */
+	int number_of_iterations = 1;
+	int num;
+	int ch;
+
+	/* Figure out if Unaligned PER needs to be default */
+	if(pduType->uper_decoder)
+		iform = INP_PER;
+
+	/*
+	 * Pocess the command-line argments.
+	 */
+	while((ch = getopt(ac, av, "i:o:1b:cdn:p:hs:" JUNKOPT)) != -1)
+	switch(ch) {
+	case 'i':
+		if(optarg[0] == 'b') { iform = INP_BER; break; }
+		if(optarg[0] == 'x') { iform = INP_XER; break; }
+		if(pduType->uper_decoder
+		&& optarg[0] == 'p') { iform = INP_PER; break; }
+		fprintf(stderr, "-i<format>: '%s': improper format selector\n",
+			optarg);
+		exit(EX_UNAVAILABLE);
+	case 'o':
+		if(optarg[0] == 'd') { oform = OUT_DER; break; }
+		if(pduType->uper_encoder
+		&& optarg[0] == 'p') { oform = OUT_PER; break; }
+		if(optarg[0] == 'x') { oform = OUT_XER; break; }
+		if(optarg[0] == 't') { oform = OUT_TEXT; break; }
+		if(optarg[0] == 'n') { oform = OUT_NULL; break; }
+		fprintf(stderr, "-o<format>: '%s': improper format selector\n",
+			optarg);
+		exit(EX_UNAVAILABLE);
+	case '1':
+		opt_onepdu = 1;
+		break;
+	case 'b':
+		suggested_bufsize = atoi(optarg);
+		if(suggested_bufsize < 1
+			|| suggested_bufsize > 16 * 1024 * 1024) {
+			fprintf(stderr,
+				"-b %s: Improper buffer size (1..16M)\n",
+				optarg);
+			exit(EX_UNAVAILABLE);
+		}
+		break;
+	case 'c':
+		opt_check = 1;
+		break;
+	case 'd':
+		opt_debug++;	/* Double -dd means ASN.1 debug */
+		break;
+	case 'n':
+		number_of_iterations = atoi(optarg);
+		if(number_of_iterations < 1) {
+			fprintf(stderr,
+				"-n %s: Improper iterations count\n", optarg);
+			exit(EX_UNAVAILABLE);
+		}
+		break;
+	case 'p':
+		if(strcmp(optarg, "er-nopad") == 0) {
+			opt_nopad = 1;
+			break;
+		}
+#ifdef	ASN_PDU_COLLECTION
+		if(strcmp(optarg, "list") == 0) {
+			asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
+			fprintf(stderr, "Available PDU types:\n");
+			for(; *pdu; pdu++) printf("%s\n", (*pdu)->name);
+			exit(0);
+		} else if(optarg[0] >= 'A' && optarg[0] <= 'Z') {
+			asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
+			while(*pdu && strcmp((*pdu)->name, optarg)) pdu++;
+			if(*pdu) { pduType = *pdu; break; }
+			fprintf(stderr, "-p %s: Unrecognized PDU\n", optarg);
+		}
+#endif	/* ASN_PDU_COLLECTION */
+		fprintf(stderr, "-p %s: Unrecognized option\n", optarg);
+		exit(EX_UNAVAILABLE);
+	case 's':
+		opt_stack = atoi(optarg);
+		if(opt_stack < 0) {
+			fprintf(stderr,
+				"-s %s: Non-negative value expected\n",
+				optarg);
+			exit(EX_UNAVAILABLE);
+		}
+		break;
+#ifdef	JUNKTEST
+	case 'J':
+		opt_jprob = strtod(optarg, 0);
+		if(opt_jprob <= 0.0 || opt_jprob > 1.0) {
+			fprintf(stderr,
+				"-J %s: Probability range 0..1 expected \n",
+				optarg);
+			exit(EX_UNAVAILABLE);
+		}
+		break;
+#endif	/* JUNKTEST */
+	case 'h':
+	default:
+#ifdef	ASN_CONVERTER_TITLE
+#define	_AXS(x)	#x
+#define	_ASX(x)	_AXS(x)
+		fprintf(stderr, "%s\n", _ASX(ASN_CONVERTER_TITLE));
+#endif
+		fprintf(stderr, "Usage: %s [options] <data.ber> ...\n", av[0]);
+		fprintf(stderr, "Where options are:\n");
+		if(pduType->uper_decoder)
+		fprintf(stderr,
+		"  -iper        Input is in Unaligned PER (Packed Encoding Rules) (DEFAULT)\n");
+		fprintf(stderr,
+		"  -iber        Input is in BER (Basic Encoding Rules)%s\n",
+			iform == INP_PER ? "" : " (DEFAULT)");
+		fprintf(stderr,
+		"  -ixer        Input is in XER (XML Encoding Rules)\n");
+		if(pduType->uper_encoder)
+		fprintf(stderr,
+		"  -oper        Output in Unaligned PER (Packed Encoding Rules)\n");
+		fprintf(stderr,
+		"  -oder        Output in DER (Distinguished Encoding Rules)\n"
+		"  -oxer        Output in XER (XML Encoding Rules) (DEFAULT)\n"
+		"  -otext       Output in plain semi-structured text (dump)\n"
+		"  -onull       Verify (decode) input, but do not output\n");
+		if(pduType->uper_decoder)
+		fprintf(stderr,
+		"  -per-nopad   Assume PER PDUs are not padded (-iper)\n");
+#ifdef	ASN_PDU_COLLECTION
+		fprintf(stderr,
+		"  -p <PDU>     Specify PDU type to decode\n"
+		"  -p list      List available PDUs\n");
+#endif	/* ASN_PDU_COLLECTION */
+		fprintf(stderr,
+		"  -1           Decode only the first PDU in file\n"
+		"  -b <size>    Set the i/o buffer size (default is %ld)\n"
+		"  -c           Check ASN.1 constraints after decoding\n"
+		"  -d           Enable debugging (-dd is even better)\n"
+		"  -n <num>     Process files <num> times\n"
+		"  -s <size>    Set the stack usage limit (default is %d)\n"
+#ifdef	JUNKTEST
+		"  -J <prob>    Set random junk test bit garbaging probability\n"
+#endif
+		, (long)suggested_bufsize, ASN__DEFAULT_STACK_MAX);
+		exit(EX_USAGE);
+	}
+
+	ac -= optind;
+	av += optind;
+
+	if(ac < 1) {
+		fprintf(stderr, "%s: No input files specified. "
+				"Try '-h' for more information\n",
+				av[-optind]);
+		exit(EX_USAGE);
+	}
+
+	setvbuf(stdout, 0, _IOLBF, 0);
+
+	for(num = 0; num < number_of_iterations; num++) {
+	  int ac_i;
+	  /*
+	   * Process all files in turn.
+	   */
+	  for(ac_i = 0; ac_i < ac; ac_i++) {
+	    asn_enc_rval_t erv;
+	    void *structure;	/* Decoded structure */
+	    FILE *file = argument_to_file(av, ac_i);
+	    char *name = argument_to_name(av, ac_i);
+	    int first_pdu;
+
+	    for(first_pdu = 1; first_pdu || !opt_onepdu; first_pdu = 0) {
+		/*
+		 * Decode the encoded structure from file.
+		 */
+		structure = data_decode_from_file(pduType,
+				file, name, suggested_bufsize, first_pdu);
+		if(!structure) {
+			if(errno) {
+				/* Error message is already printed */
+				exit(EX_DATAERR);
+			} else {
+				/* EOF */
+				break;
+			}
+		}
+
+		/* Check ASN.1 constraints */
+		if(opt_check) {
+			char errbuf[128];
+			size_t errlen = sizeof(errbuf);
+			if(asn_check_constraints(pduType, structure,
+				errbuf, &errlen)) {
+				fprintf(stderr, "%s: ASN.1 constraint "
+					"check failed: %s\n", name, errbuf);
+				exit(EX_DATAERR);
+			}
+		}
+
+		switch(oform) {
+		case OUT_NULL:
+#ifdef	JUNKTEST
+		    if(opt_jprob == 0.0)
+#endif
+			fprintf(stderr, "%s: decoded successfully\n", name);
+			break;
+		case OUT_TEXT:	/* -otext */
+			asn_fprint(stdout, pduType, structure);
+			break;
+		case OUT_XER:	/* -oxer */
+			if(xer_fprint(stdout, pduType, structure)) {
+				fprintf(stderr,
+					"%s: Cannot convert %s into XML\n",
+					name, pduType->name);
+				exit(EX_UNAVAILABLE);
+			}
+			break;
+		case OUT_DER:
+			erv = der_encode(pduType, structure, write_out, stdout);
+			if(erv.encoded < 0) {
+				fprintf(stderr,
+					"%s: Cannot convert %s into DER\n",
+					name, pduType->name);
+				exit(EX_UNAVAILABLE);
+			}
+			DEBUG("Encoded in %ld bytes of DER", (long)erv.encoded);
+			break;
+		case OUT_PER:
+			erv = uper_encode(pduType, structure, write_out, stdout);
+			if(erv.encoded < 0) {
+				fprintf(stderr,
+				"%s: Cannot convert %s into Unaligned PER\n",
+					name, pduType->name);
+				exit(EX_UNAVAILABLE);
+			}
+			DEBUG("Encoded in %ld bits of UPER", (long)erv.encoded);
+			break;
+		}
+
+		ASN_STRUCT_FREE(*pduType, structure);
+	    }
+
+	    if(file && file != stdin)
+		fclose(file);
+	  }
+	}
+
+#ifdef	JUNKTEST
+	if(opt_jprob > 0.0) {
+		fprintf(stderr, "Junked %f OK (%d/%d)\n",
+			opt_jprob, junk_failures, number_of_iterations);
+	}
+#endif	/* JUNKTEST */
+
+	return 0;
+}
+
+static struct dynamic_buffer {
+	uint8_t *data;		/* Pointer to the data bytes */
+	size_t offset;		/* Offset from the start */
+	size_t length;		/* Length of meaningful contents */
+	size_t unbits;		/* Unused bits in the last byte */
+	size_t allocated;	/* Allocated memory for data */
+	int    nreallocs;	/* Number of data reallocations */
+	off_t  bytes_shifted;	/* Number of bytes ever shifted */
+} DynamicBuffer;
+
+static void
+buffer_dump() {
+	uint8_t *p = DynamicBuffer.data + DynamicBuffer.offset;
+	uint8_t *e = p + DynamicBuffer.length - (DynamicBuffer.unbits ? 1 : 0);
+	if(!opt_debug) return;
+	DEBUG("Buffer: { d=%p, o=%ld, l=%ld, u=%ld, a=%ld, s=%ld }",
+		DynamicBuffer.data,
+		(long)DynamicBuffer.offset,
+		(long)DynamicBuffer.length,
+		(long)DynamicBuffer.unbits,
+		(long)DynamicBuffer.allocated,
+		(long)DynamicBuffer.bytes_shifted);
+	for(; p < e; p++) {
+		fprintf(stderr, " %c%c%c%c%c%c%c%c",
+			((*p >> 7) & 1) ? '1' : '0',
+			((*p >> 6) & 1) ? '1' : '0',
+			((*p >> 5) & 1) ? '1' : '0',
+			((*p >> 4) & 1) ? '1' : '0',
+			((*p >> 3) & 1) ? '1' : '0',
+			((*p >> 2) & 1) ? '1' : '0',
+			((*p >> 1) & 1) ? '1' : '0',
+			((*p >> 0) & 1) ? '1' : '0');
+	}
+	if(DynamicBuffer.unbits) {
+		unsigned int shift;
+		fprintf(stderr, " ");
+		for(shift = 7; shift >= DynamicBuffer.unbits; shift--)
+			fprintf(stderr, "%c", ((*p >> shift) & 1) ? '1' : '0');
+		fprintf(stderr, " %ld:%ld\n",
+			(long)DynamicBuffer.length - 1,
+			(long)8 - DynamicBuffer.unbits);
+	} else {
+		fprintf(stderr, " %ld\n", (long)DynamicBuffer.length);
+	}
+}
+
+/*
+ * Move the buffer content left N bits, possibly joining it with
+ * preceeding content.
+ */
+static void
+buffer_shift_left(size_t offset, int bits) {
+	uint8_t *ptr = DynamicBuffer.data + DynamicBuffer.offset + offset;
+	uint8_t *end = DynamicBuffer.data + DynamicBuffer.offset
+			+ DynamicBuffer.length - 1;
+	
+	if(!bits) return;
+
+	DEBUG("Shifting left %d bits off %ld (o=%ld, u=%ld, l=%ld)",
+		bits, (long)offset,
+		(long)DynamicBuffer.offset,
+		(long)DynamicBuffer.unbits,
+		(long)DynamicBuffer.length);
+
+	if(offset) {
+		int right;
+		right = ptr[0] >> (8 - bits);
+
+		DEBUG("oleft: %c%c%c%c%c%c%c%c",
+			((ptr[-1] >> 7) & 1) ? '1' : '0',
+			((ptr[-1] >> 6) & 1) ? '1' : '0',
+			((ptr[-1] >> 5) & 1) ? '1' : '0',
+			((ptr[-1] >> 4) & 1) ? '1' : '0',
+			((ptr[-1] >> 3) & 1) ? '1' : '0',
+			((ptr[-1] >> 2) & 1) ? '1' : '0',
+			((ptr[-1] >> 1) & 1) ? '1' : '0',
+			((ptr[-1] >> 0) & 1) ? '1' : '0');
+
+		DEBUG("oriht: %c%c%c%c%c%c%c%c",
+			((ptr[0] >> 7) & 1) ? '1' : '0',
+			((ptr[0] >> 6) & 1) ? '1' : '0',
+			((ptr[0] >> 5) & 1) ? '1' : '0',
+			((ptr[0] >> 4) & 1) ? '1' : '0',
+			((ptr[0] >> 3) & 1) ? '1' : '0',
+			((ptr[0] >> 2) & 1) ? '1' : '0',
+			((ptr[0] >> 1) & 1) ? '1' : '0',
+			((ptr[0] >> 0) & 1) ? '1' : '0');
+
+		DEBUG("mriht: %c%c%c%c%c%c%c%c",
+			((right >> 7) & 1) ? '1' : '0',
+			((right >> 6) & 1) ? '1' : '0',
+			((right >> 5) & 1) ? '1' : '0',
+			((right >> 4) & 1) ? '1' : '0',
+			((right >> 3) & 1) ? '1' : '0',
+			((right >> 2) & 1) ? '1' : '0',
+			((right >> 1) & 1) ? '1' : '0',
+			((right >> 0) & 1) ? '1' : '0');
+
+		ptr[-1] = (ptr[-1] & (0xff << bits)) | right;
+
+		DEBUG("after: %c%c%c%c%c%c%c%c",
+			((ptr[-1] >> 7) & 1) ? '1' : '0',
+			((ptr[-1] >> 6) & 1) ? '1' : '0',
+			((ptr[-1] >> 5) & 1) ? '1' : '0',
+			((ptr[-1] >> 4) & 1) ? '1' : '0',
+			((ptr[-1] >> 3) & 1) ? '1' : '0',
+			((ptr[-1] >> 2) & 1) ? '1' : '0',
+			((ptr[-1] >> 1) & 1) ? '1' : '0',
+			((ptr[-1] >> 0) & 1) ? '1' : '0');
+	}
+
+	buffer_dump();
+
+	for(; ptr < end; ptr++) {
+		int right = ptr[1] >> (8 - bits);
+		*ptr = (*ptr << bits) | right;
+	}
+	*ptr <<= bits;
+
+	DEBUG("Unbits [%d=>", (int)DynamicBuffer.unbits);
+	if(DynamicBuffer.unbits == 0) {
+		DynamicBuffer.unbits += bits;
+	} else {
+		DynamicBuffer.unbits += bits;
+		if(DynamicBuffer.unbits > 7) {
+			DynamicBuffer.unbits -= 8;
+			DynamicBuffer.length--;
+			DynamicBuffer.bytes_shifted++;
+		}
+	}
+	DEBUG("Unbits =>%d]", (int)DynamicBuffer.unbits);
+
+	buffer_dump();
+
+	DEBUG("Shifted. Now (o=%ld, u=%ld l=%ld)",
+		(long)DynamicBuffer.offset,
+		(long)DynamicBuffer.unbits,
+		(long)DynamicBuffer.length);
+	
+
+}
+
+/*
+ * Ensure that the buffer contains at least this amount of free space.
+ */
+static void add_bytes_to_buffer(const void *data2add, size_t bytes) {
+
+	if(bytes == 0) return;
+
+	DEBUG("=> add_bytes(%ld) { o=%ld l=%ld u=%ld, s=%ld }",
+		(long)bytes,
+		(long)DynamicBuffer.offset,
+		(long)DynamicBuffer.length,
+		(long)DynamicBuffer.unbits,
+		(long)DynamicBuffer.allocated);
+
+	if(DynamicBuffer.allocated
+	>= (DynamicBuffer.offset + DynamicBuffer.length + bytes)) {
+		DEBUG("\tNo buffer reallocation is necessary");
+	} else if(bytes <= DynamicBuffer.offset) {
+		DEBUG("\tContents shifted by %ld", DynamicBuffer.offset);
+
+		/* Shift the buffer contents */
+		memmove(DynamicBuffer.data,
+		        DynamicBuffer.data + DynamicBuffer.offset,
+			DynamicBuffer.length);
+		DynamicBuffer.bytes_shifted += DynamicBuffer.offset;
+		DynamicBuffer.offset = 0;
+	} else {
+		size_t newsize = (DynamicBuffer.allocated << 2) + bytes;
+		void *p = MALLOC(newsize);
+		if(!p) {
+			perror("malloc()");
+			exit(EX_OSERR);
+		}
+		memcpy(p,
+			DynamicBuffer.data + DynamicBuffer.offset,
+			DynamicBuffer.length);
+		FREEMEM(DynamicBuffer.data);
+		DynamicBuffer.data = (uint8_t *)p;
+		DynamicBuffer.offset = 0;
+		DynamicBuffer.allocated = newsize;
+		DynamicBuffer.nreallocs++;
+		DEBUG("\tBuffer reallocated to %ld (%d time)",
+			newsize, DynamicBuffer.nreallocs);
+	}
+
+	memcpy(DynamicBuffer.data
+		+ DynamicBuffer.offset + DynamicBuffer.length,
+		data2add, bytes);
+	DynamicBuffer.length += bytes;
+	if(DynamicBuffer.unbits) {
+		int bits = DynamicBuffer.unbits;
+		DynamicBuffer.unbits = 0;
+		buffer_shift_left(DynamicBuffer.length - bytes, bits);
+	}
+
+	DEBUG("<= add_bytes(%ld) { o=%ld l=%ld u=%ld, s=%ld }",
+		(long)bytes,
+		(long)DynamicBuffer.offset,
+		(long)DynamicBuffer.length,
+		(long)DynamicBuffer.unbits,
+		(long)DynamicBuffer.allocated);
+}
+
+static void *
+data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *name, ssize_t suggested_bufsize, int on_first_pdu) {
+	static uint8_t *fbuf;
+	static ssize_t fbuf_size;
+	static asn_codec_ctx_t s_codec_ctx;
+	asn_codec_ctx_t *opt_codec_ctx = 0;
+	void *structure = 0;
+	asn_dec_rval_t rval;
+	size_t old_offset;	
+	size_t new_offset;
+	int tolerate_eof;
+	size_t rd;
+
+	if(!file) {
+		fprintf(stderr, "%s: %s\n", name, strerror(errno));
+		errno = EINVAL;
+		return 0;
+	}
+
+	if(opt_stack) {
+		s_codec_ctx.max_stack_size = opt_stack;
+		opt_codec_ctx = &s_codec_ctx;
+	}
+
+	DEBUG("Processing %s", name);
+
+	/* prepare the file buffer */
+	if(fbuf_size != suggested_bufsize) {
+		fbuf = (uint8_t *)REALLOC(fbuf, suggested_bufsize);
+		if(!fbuf) {
+			perror("realloc()");
+			exit(EX_OSERR);
+		}
+		fbuf_size = suggested_bufsize;
+	}
+
+	if(on_first_pdu) {
+		DynamicBuffer.offset = 0;
+		DynamicBuffer.length = 0;
+		DynamicBuffer.unbits = 0;
+		DynamicBuffer.allocated = 0;
+		DynamicBuffer.bytes_shifted = 0;
+		DynamicBuffer.nreallocs = 0;
+	}
+
+	old_offset = DynamicBuffer.bytes_shifted + DynamicBuffer.offset;
+
+	/* Pretend immediate EOF */
+	rval.code = RC_WMORE;
+	rval.consumed = 0;
+
+	for(tolerate_eof = 1;	/* Allow EOF first time buffer is non-empty */
+	    (rd = fread(fbuf, 1, fbuf_size, file))
+		|| feof(file) == 0
+		|| (tolerate_eof && DynamicBuffer.length)
+	    ;) {
+		int      ecbits = 0;	/* Extra consumed bits in case of PER */
+		uint8_t *i_bptr;
+		size_t   i_size;
+
+		/*
+		 * Copy the data over, or use the original buffer.
+		 */
+		if(DynamicBuffer.allocated) {
+			/* Append new data into the existing dynamic buffer */
+			add_bytes_to_buffer(fbuf, rd);
+			i_bptr = DynamicBuffer.data + DynamicBuffer.offset;
+			i_size = DynamicBuffer.length;
+		} else {
+			i_bptr = fbuf;
+			i_size = rd;
+		}
+
+		DEBUG("Decoding %ld bytes", (long)i_size);
+
+#ifdef	JUNKTEST
+		junk_bytes_with_probability(i_bptr, i_size, opt_jprob);
+#endif
+
+		switch(iform) {
+		case INP_BER:
+			rval = ber_decode(opt_codec_ctx, pduType,
+				(void **)&structure, i_bptr, i_size);
+			break;
+		case INP_XER:
+			rval = xer_decode(opt_codec_ctx, pduType,
+				(void **)&structure, i_bptr, i_size);
+			break;
+		case INP_PER:
+			if(opt_nopad)
+			rval = uper_decode(opt_codec_ctx, pduType,
+				(void **)&structure, i_bptr, i_size, 0,
+				DynamicBuffer.unbits);
+			else
+			rval = uper_decode_complete(opt_codec_ctx, pduType,
+				(void **)&structure, i_bptr, i_size);
+			switch(rval.code) {
+			case RC_OK:
+				/* Fall through */
+			case RC_FAIL:
+				if(opt_nopad) {
+					/* uper_decode() returns bits! */
+					/* Extra bits */
+					ecbits = rval.consumed % 8;
+					/* Convert into bytes! */
+					rval.consumed /= 8;
+				}
+				break;
+			case RC_WMORE:
+				/* PER does not support restartability */
+				ASN_STRUCT_FREE(*pduType, structure);
+				structure = 0;
+				rval.consumed = 0;
+				/* Continue accumulating data */
+				break;
+			}
+			break;
+		}
+		DEBUG("decode(%ld) consumed %ld+%db (%ld), code %d",
+			(long)DynamicBuffer.length,
+			(long)rval.consumed, ecbits, (long)i_size,
+			rval.code);
+
+		if(DynamicBuffer.allocated == 0) {
+			/*
+			 * Flush remainder into the intermediate buffer.
+			 */
+			if(rval.code != RC_FAIL && rval.consumed < rd) {
+				add_bytes_to_buffer(fbuf + rval.consumed,
+					rd - rval.consumed);
+				buffer_shift_left(0, ecbits);
+				DynamicBuffer.bytes_shifted = rval.consumed;
+				rval.consumed = 0;
+				ecbits = 0;
+			}
+		}
+
+		/*
+		 * Adjust position inside the source buffer.
+		 */
+		if(DynamicBuffer.allocated) {
+			DynamicBuffer.offset += rval.consumed;
+			DynamicBuffer.length -= rval.consumed;
+		} else {
+			DynamicBuffer.bytes_shifted += rval.consumed;
+		}
+
+		switch(rval.code) {
+		case RC_OK:
+			if(ecbits) buffer_shift_left(0, ecbits);
+			DEBUG("RC_OK, finishing up with %ld+%d",
+				(long)rval.consumed, ecbits);
+			return structure;
+		case RC_WMORE:
+			DEBUG("RC_WMORE, continuing read=%ld, cons=%ld "
+				" with %ld..%ld-%ld..%ld",
+				(long)rd,
+				(long)rval.consumed,
+				(long)DynamicBuffer.offset,
+				(long)DynamicBuffer.length,
+				(long)DynamicBuffer.unbits,
+				(long)DynamicBuffer.allocated);
+			if(!rd) tolerate_eof--;
+			continue;
+		case RC_FAIL:
+			break;
+		}
+		break;
+	}
+
+	DEBUG("Clean up partially decoded structure");
+	ASN_STRUCT_FREE(*pduType, structure);
+
+	new_offset = DynamicBuffer.bytes_shifted + DynamicBuffer.offset;
+
+	/*
+	 * Print a message and return failure only if not EOF,
+	 * unless this is our first PDU (empty file).
+	 */
+	if(on_first_pdu
+	|| DynamicBuffer.length
+	|| new_offset - old_offset > ((iform == INP_XER)?sizeof("\r\n")-1:0)
+	) {
+
+#ifdef	JUNKTEST
+		/*
+		 * Nothing's wrong with being unable to decode junk.
+		 * Simulate EOF.
+		 */
+		if(opt_jprob != 0.0) {
+			junk_failures++;
+			errno = 0;
+			return 0;
+		}
+#endif
+
+		DEBUG("ofp %d, no=%ld, oo=%ld, dbl=%ld",
+			on_first_pdu, (long)new_offset, (long)old_offset,
+			(long)DynamicBuffer.length);
+		fprintf(stderr, "%s: "
+			"Decode failed past byte %ld: %s\n",
+			name, (long)new_offset,
+			(rval.code == RC_WMORE)
+				? "Unexpected end of input"
+				: "Input processing error");
+#ifndef	ENOMSG
+#define	ENOMSG EINVAL
+#endif
+#ifndef	EBADMSG
+#define	EBADMSG EINVAL
+#endif
+		errno = (rval.code == RC_WMORE) ? ENOMSG : EBADMSG;
+	} else {
+		/* Got EOF after a few successful PDUs */
+		errno = 0;
+	}
+
+	return 0;
+}
+
+/* Dump the buffer out to the specified FILE */
+static int write_out(const void *buffer, size_t size, void *key) {
+	FILE *fp = (FILE *)key;
+	return (fwrite(buffer, 1, size, fp) == size) ? 0 : -1;
+}
+
+static int argument_is_stdin(char *av[], int idx) {
+	if(strcmp(av[idx], "-")) {
+		return 0;	/* Certainly not <stdin> */
+	} else {
+		/* This might be <stdin>, unless `./program -- -` */
+		if(strcmp(av[-1], "--"))
+			return 1;
+		else
+			return 0;
+	}
+}
+
+static FILE *argument_to_file(char *av[], int idx) {
+	return argument_is_stdin(av, idx)
+		? stdin
+		: fopen(av[idx], "rb");
+}
+
+static char *argument_to_name(char *av[], int idx) {
+	return argument_is_stdin(av, idx)
+		? "standard input"
+		: av[idx];
+}
+
+#ifdef	JUNKTEST
+/*
+ * Fill bytes with some garbage with specified probability (more or less).
+ */
+static void
+junk_bytes_with_probability(uint8_t *buf, size_t size, double prob) {
+	static int junkmode;
+	uint8_t *ptr;
+	uint8_t *end;
+	if(opt_jprob <= 0.0) return;
+	for(ptr = buf, end = ptr + size; ptr < end; ptr++) {
+		int byte = *ptr;
+		if(junkmode++ & 1) {
+			if((((double)random() / RAND_MAX) < prob))
+				byte = random() & 0xff;
+		} else {
+#define	BPROB(b)	((((double)random() / RAND_MAX) < prob) ? b : 0)
+			byte ^= BPROB(0x80);
+			byte ^= BPROB(0x40);
+			byte ^= BPROB(0x20);
+			byte ^= BPROB(0x10);
+			byte ^= BPROB(0x08);
+			byte ^= BPROB(0x04);
+			byte ^= BPROB(0x02);
+			byte ^= BPROB(0x01);
+		}
+		if(byte != *ptr) {
+			DEBUG("Junk buf[%d] %02x -> %02x",
+				ptr - buf, *ptr, byte);
+			*ptr = byte;
+		}
+	}
+}
+#endif	/* JUNKTEST */
+
diff --git a/libkmod/pkcs7/asn1c-gen/der_encoder.c b/libkmod/pkcs7/asn1c-gen/der_encoder.c
new file mode 100644
index 000000000000..1c014802a8e8
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/der_encoder.c
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <errno.h>
+
+static ssize_t der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len,
+	asn_app_consume_bytes_f *cb, void *app_key, int constructed);
+
+/*
+ * The DER encoder of any type.
+ */
+asn_enc_rval_t
+der_encode(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
+	asn_app_consume_bytes_f *consume_bytes, void *app_key) {
+
+	ASN_DEBUG("DER encoder invoked for %s",
+		type_descriptor->name);
+
+	/*
+	 * Invoke type-specific encoder.
+	 */
+	return type_descriptor->der_encoder(type_descriptor,
+		struct_ptr,	/* Pointer to the destination structure */
+		0, 0,
+		consume_bytes, app_key);
+}
+
+/*
+ * Argument type and callback necessary for der_encode_to_buffer().
+ */
+typedef struct enc_to_buf_arg {
+	void *buffer;
+	size_t left;
+} enc_to_buf_arg;
+static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
+	enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
+
+	if(arg->left < size)
+		return -1;	/* Data exceeds the available buffer size */
+
+	memcpy(arg->buffer, buffer, size);
+	arg->buffer = ((char *)arg->buffer) + size;
+	arg->left -= size;
+
+	return 0;
+}
+
+/*
+ * A variant of the der_encode() which encodes the data into the provided buffer
+ */
+asn_enc_rval_t
+der_encode_to_buffer(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
+	void *buffer, size_t buffer_size) {
+	enc_to_buf_arg arg;
+	asn_enc_rval_t ec;
+
+	arg.buffer = buffer;
+	arg.left = buffer_size;
+
+	ec = type_descriptor->der_encoder(type_descriptor,
+		struct_ptr,	/* Pointer to the destination structure */
+		0, 0, encode_to_buffer_cb, &arg);
+	if(ec.encoded != -1) {
+		assert(ec.encoded == (ssize_t)(buffer_size - arg.left));
+		/* Return the encoded contents size */
+	}
+	return ec;
+}
+
+
+/*
+ * Write out leading TL[v] sequence according to the type definition.
+ */
+ssize_t
+der_write_tags(asn_TYPE_descriptor_t *sd,
+		size_t struct_length,
+		int tag_mode, int last_tag_form,
+		ber_tlv_tag_t tag,	/* EXPLICIT or IMPLICIT tag */
+		asn_app_consume_bytes_f *cb,
+		void *app_key) {
+	const ber_tlv_tag_t *tags;	/* Copy of tags stream */
+	int tags_count;			/* Number of tags */
+	size_t overall_length;
+	ssize_t *lens;
+	int i;
+
+	ASN_DEBUG("Writing tags (%s, tm=%d, tc=%d, tag=%s, mtc=%d)",
+		sd->name, tag_mode, sd->tags_count,
+		ber_tlv_tag_string(tag),
+		tag_mode
+			?(sd->tags_count+1
+				-((tag_mode == -1) && sd->tags_count))
+			:sd->tags_count
+	);
+
+	if(tag_mode) {
+		/*
+		 * Instead of doing shaman dance like we do in ber_check_tags(),
+		 * allocate a small array on the stack
+		 * and initialize it appropriately.
+		 */
+		int stag_offset;
+		ber_tlv_tag_t *tags_buf;
+		tags_buf = (ber_tlv_tag_t *)alloca((sd->tags_count + 1) * sizeof(ber_tlv_tag_t));
+		if(!tags_buf) {	/* Can fail on !x86 */
+			errno = ENOMEM;
+			return -1;
+		}
+		tags_count = sd->tags_count
+			+ 1	/* EXPLICIT or IMPLICIT tag is given */
+			- ((tag_mode == -1) && sd->tags_count);
+		/* Copy tags over */
+		tags_buf[0] = tag;
+		stag_offset = -1 + ((tag_mode == -1) && sd->tags_count);
+		for(i = 1; i < tags_count; i++)
+			tags_buf[i] = sd->tags[i + stag_offset];
+		tags = tags_buf;
+	} else {
+		tags = sd->tags;
+		tags_count = sd->tags_count;
+	}
+
+	/* No tags to write */
+	if(tags_count == 0)
+		return 0;
+
+	lens = (ssize_t *)alloca(tags_count * sizeof(lens[0]));
+	if(!lens) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	/*
+	 * Array of tags is initialized.
+	 * Now, compute the size of the TLV pairs, from right to left.
+	 */
+	overall_length = struct_length;
+	for(i = tags_count - 1; i >= 0; --i) {
+		lens[i] = der_write_TL(tags[i], overall_length, 0, 0, 0);
+		if(lens[i] == -1) return -1;
+		overall_length += lens[i];
+		lens[i] = overall_length - lens[i];
+	}
+
+	if(!cb) return overall_length - struct_length;
+
+	ASN_DEBUG("%s %s TL sequence (%d elements)",
+		cb?"Encoding":"Estimating", sd->name, tags_count);
+
+	/*
+	 * Encode the TL sequence for real.
+	 */
+	for(i = 0; i < tags_count; i++) {
+		ssize_t len;
+		int _constr;
+
+		/* Check if this tag happens to be constructed */
+		_constr = (last_tag_form || i < (tags_count - 1));
+
+		len = der_write_TL(tags[i], lens[i], cb, app_key, _constr);
+		if(len == -1) return -1;
+	}
+
+	return overall_length - struct_length;
+}
+
+static ssize_t
+der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len,
+		asn_app_consume_bytes_f *cb, void *app_key,
+		int constructed) {
+	uint8_t buf[32];
+	size_t size = 0;
+	int buf_size = cb?sizeof(buf):0;
+	ssize_t tmp;
+
+	/* Serialize tag (T from TLV) into possibly zero-length buffer */
+	tmp = ber_tlv_tag_serialize(tag, buf, buf_size);
+	if(tmp == -1 || tmp > (ssize_t)sizeof(buf)) return -1;
+	size += tmp;
+
+	/* Serialize length (L from TLV) into possibly zero-length buffer */
+	tmp = der_tlv_length_serialize(len, buf+size, buf_size?buf_size-size:0);
+	if(tmp == -1) return -1;
+	size += tmp;
+
+	if(size > sizeof(buf))
+		return -1;
+
+	/*
+	 * If callback is specified, invoke it, and check its return value.
+	 */
+	if(cb) {
+		if(constructed) *buf |= 0x20;
+		if(cb(buf, size, app_key) < 0)
+			return -1;
+	}
+
+	return size;
+}
diff --git a/libkmod/pkcs7/asn1c-gen/der_encoder.h b/libkmod/pkcs7/asn1c-gen/der_encoder.h
new file mode 100644
index 000000000000..61431c6dbdc8
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/der_encoder.h
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_DER_ENCODER_H_
+#define	_DER_ENCODER_H_
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;	/* Forward declaration */
+
+/*
+ * The DER encoder of any type. May be invoked by the application.
+ * The ber_decode() function (ber_decoder.h) is an opposite of der_encode().
+ */
+asn_enc_rval_t der_encode(struct asn_TYPE_descriptor_s *type_descriptor,
+		void *struct_ptr,	/* Structure to be encoded */
+		asn_app_consume_bytes_f *consume_bytes_cb,
+		void *app_key		/* Arbitrary callback argument */
+	);
+
+/* A variant of der_encode() which encodes data into the pre-allocated buffer */
+asn_enc_rval_t der_encode_to_buffer(
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		void *struct_ptr,	/* Structure to be encoded */
+		void *buffer,		/* Pre-allocated buffer */
+		size_t buffer_size	/* Initial buffer size (maximum) */
+	);
+
+/*
+ * Type of the generic DER encoder.
+ */
+typedef asn_enc_rval_t (der_type_encoder_f)(
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		void *struct_ptr,	/* Structure to be encoded */
+		int tag_mode,		/* {-1,0,1}: IMPLICIT, no, EXPLICIT */
+		ber_tlv_tag_t tag,
+		asn_app_consume_bytes_f *consume_bytes_cb,	/* Callback */
+		void *app_key		/* Arbitrary callback argument */
+	);
+
+
+/*******************************
+ * INTERNALLY USEFUL FUNCTIONS *
+ *******************************/
+
+/*
+ * Write out leading TL[v] sequence according to the type definition.
+ */
+ssize_t der_write_tags(
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		size_t struct_length,
+		int tag_mode,		/* {-1,0,1}: IMPLICIT, no, EXPLICIT */
+		int last_tag_form,	/* {0,!0}: prim, constructed */
+		ber_tlv_tag_t tag,
+		asn_app_consume_bytes_f *consume_bytes_cb,
+		void *app_key
+	);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _DER_ENCODER_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/per_decoder.c b/libkmod/pkcs7/asn1c-gen/per_decoder.c
new file mode 100644
index 000000000000..461b7262f1d9
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/per_decoder.c
@@ -0,0 +1,93 @@
+#include <asn_application.h>
+#include <asn_internal.h>
+#include <per_decoder.h>
+
+/*
+ * Decode a "Production of a complete encoding", X.691#10.1.
+ * The complete encoding contains at least one byte, and is an integral
+ * multiple of 8 bytes.
+ */
+asn_dec_rval_t
+uper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size) {
+	asn_dec_rval_t rval;
+
+	rval = uper_decode(opt_codec_ctx, td, sptr, buffer, size, 0, 0);
+	if(rval.consumed) {
+		/*
+		 * We've always given 8-aligned data,
+		 * so convert bits to integral bytes.
+		 */
+		rval.consumed += 7;
+		rval.consumed >>= 3;
+	} else if(rval.code == RC_OK) {
+		if(size) {
+			if(((const uint8_t *)buffer)[0] == 0) {
+				rval.consumed = 1;	/* 1 byte */
+			} else {
+				ASN_DEBUG("Expecting single zeroed byte");
+				rval.code = RC_FAIL;
+			}
+		} else {
+			/* Must contain at least 8 bits. */
+			rval.code = RC_WMORE;
+		}
+	}
+
+	return rval;
+}
+
+asn_dec_rval_t
+uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) {
+	asn_codec_ctx_t s_codec_ctx;
+	asn_dec_rval_t rval;
+	asn_per_data_t pd;
+
+	if(skip_bits < 0 || skip_bits > 7
+	|| unused_bits < 0 || unused_bits > 7
+	|| (unused_bits > 0 && !size))
+		ASN__DECODE_FAILED;
+
+	/*
+	 * Stack checker requires that the codec context
+	 * must be allocated on the stack.
+	 */
+	if(opt_codec_ctx) {
+		if(opt_codec_ctx->max_stack_size) {
+			s_codec_ctx = *opt_codec_ctx;
+			opt_codec_ctx = &s_codec_ctx;
+		}
+	} else {
+		/* If context is not given, be security-conscious anyway */
+		memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
+		s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
+		opt_codec_ctx = &s_codec_ctx;
+	}
+
+	/* Fill in the position indicator */
+	memset(&pd, 0, sizeof(pd));
+	pd.buffer = (const uint8_t *)buffer;
+	pd.nboff = skip_bits;
+	pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from <limits.h> */
+	if(pd.nboff > pd.nbits)
+		ASN__DECODE_FAILED;
+
+	/*
+	 * Invoke type-specific decoder.
+	 */
+	if(!td->uper_decoder)
+		ASN__DECODE_FAILED;	/* PER is not compiled in */
+	rval = td->uper_decoder(opt_codec_ctx, td, 0, sptr, &pd);
+	if(rval.code == RC_OK) {
+		/* Return the number of consumed bits */
+		rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
+					+ pd.nboff - skip_bits;
+		ASN_DEBUG("PER decoding consumed %ld, counted %ld",
+			(long)rval.consumed, (long)pd.moved);
+		assert(rval.consumed == pd.moved);
+	} else {
+		/* PER codec is not a restartable */
+		rval.consumed = 0;
+	}
+	return rval;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/per_decoder.h b/libkmod/pkcs7/asn1c-gen/per_decoder.h
new file mode 100644
index 000000000000..8397a545fb9b
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/per_decoder.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2005, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_PER_DECODER_H_
+#define	_PER_DECODER_H_
+
+#include <asn_application.h>
+#include <per_support.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;	/* Forward declaration */
+
+/*
+ * Unaligned PER decoder of a "complete encoding" as per X.691#10.1.
+ * On success, this call always returns (.consumed >= 1), as per X.691#10.1.3.
+ */
+asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx,
+	struct asn_TYPE_descriptor_s *type_descriptor,	/* Type to decode */
+	void **struct_ptr,	/* Pointer to a target structure's pointer */
+	const void *buffer,	/* Data to be decoded */
+	size_t size		/* Size of data buffer */
+	);
+
+/*
+ * Unaligned PER decoder of any ASN.1 type. May be invoked by the application.
+ * WARNING: This call returns the number of BITS read from the stream. Beware.
+ */
+asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
+	struct asn_TYPE_descriptor_s *type_descriptor,	/* Type to decode */
+	void **struct_ptr,	/* Pointer to a target structure's pointer */
+	const void *buffer,	/* Data to be decoded */
+	size_t size,		/* Size of data buffer */
+	int skip_bits,		/* Number of unused leading bits, 0..7 */
+	int unused_bits		/* Number of unused tailing bits, 0..7 */
+	);
+
+
+/*
+ * Type of the type-specific PER decoder function.
+ */
+typedef asn_dec_rval_t (per_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx,
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		asn_per_constraints_t *constraints,
+		void **struct_ptr,
+		asn_per_data_t *per_data
+	);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _PER_DECODER_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/per_encoder.c b/libkmod/pkcs7/asn1c-gen/per_encoder.c
new file mode 100644
index 000000000000..47f3c916dacb
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/per_encoder.c
@@ -0,0 +1,151 @@
+#include <asn_application.h>
+#include <asn_internal.h>
+#include <per_encoder.h>
+
+static asn_enc_rval_t uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key);
+
+asn_enc_rval_t
+uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
+	return uper_encode_internal(td, 0, sptr, cb, app_key);
+}
+
+/*
+ * Argument type and callback necessary for uper_encode_to_buffer().
+ */
+typedef struct enc_to_buf_arg {
+	void *buffer;
+	size_t left;
+} enc_to_buf_arg;
+static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
+	enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
+
+	if(arg->left < size)
+		return -1;	/* Data exceeds the available buffer size */
+
+	memcpy(arg->buffer, buffer, size);
+	arg->buffer = ((char *)arg->buffer) + size;
+	arg->left -= size;
+
+	return 0;
+}
+
+asn_enc_rval_t
+uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
+	enc_to_buf_arg key;
+
+	key.buffer = buffer;
+	key.left = buffer_size;
+
+	if(td) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
+
+	return uper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key);
+}
+
+typedef struct enc_dyn_arg {
+	void *buffer;
+	size_t length;
+	size_t allocated;
+} enc_dyn_arg;
+static int
+encode_dyn_cb(const void *buffer, size_t size, void *key) {
+	enc_dyn_arg *arg = key;
+	if(arg->length + size >= arg->allocated) {
+		void *p;
+		arg->allocated = arg->allocated ? (arg->allocated << 2) : size;
+		p = REALLOC(arg->buffer, arg->allocated);
+		if(!p) {
+			FREEMEM(arg->buffer);
+			memset(arg, 0, sizeof(*arg));
+			return -1;
+		}
+		arg->buffer = p;
+	}
+	memcpy(((char *)arg->buffer) + arg->length, buffer, size);
+	arg->length += size;
+	return 0;
+}
+ssize_t
+uper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, void **buffer_r) {
+	asn_enc_rval_t er;
+	enc_dyn_arg key;
+
+	memset(&key, 0, sizeof(key));
+
+	er = uper_encode_internal(td, constraints, sptr, encode_dyn_cb, &key);
+	switch(er.encoded) {
+	case -1:
+		FREEMEM(key.buffer);
+		return -1;
+	case 0:
+		FREEMEM(key.buffer);
+		key.buffer = MALLOC(1);
+		if(key.buffer) {
+			*(char *)key.buffer = '\0';
+			*buffer_r = key.buffer;
+			return 1;
+		} else {
+			return -1;
+		}
+	default:
+		*buffer_r = key.buffer;
+		ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
+		return ((er.encoded + 7) >> 3);
+	}
+}
+
+/*
+ * Internally useful functions.
+ */
+
+/* Flush partially filled buffer */
+static int
+_uper_encode_flush_outp(asn_per_outp_t *po) {
+	uint8_t *buf;
+
+	if(po->nboff == 0 && po->buffer == po->tmpspace)
+		return 0;
+
+	buf = po->buffer + (po->nboff >> 3);
+	/* Make sure we account for the last, partially filled */
+	if(po->nboff & 0x07) {
+		buf[0] &= 0xff << (8 - (po->nboff & 0x07));
+		buf++;
+	}
+
+	return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
+}
+
+static asn_enc_rval_t
+uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_per_outp_t po;
+	asn_enc_rval_t er;
+
+	/*
+	 * Invoke type-specific encoder.
+	 */
+	if(!td || !td->uper_encoder)
+		ASN__ENCODE_FAILED;	/* PER is not compiled in */
+
+	po.buffer = po.tmpspace;
+	po.nboff = 0;
+	po.nbits = 8 * sizeof(po.tmpspace);
+	po.outper = cb;
+	po.op_key = app_key;
+	po.flushed_bytes = 0;
+
+	er = td->uper_encoder(td, constraints, sptr, &po);
+	if(er.encoded != -1) {
+		size_t bits_to_flush;
+
+		bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
+
+		/* Set number of bits encoded to a firm value */
+		er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
+
+		if(_uper_encode_flush_outp(&po))
+			ASN__ENCODE_FAILED;
+	}
+
+	return er;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/per_encoder.h b/libkmod/pkcs7/asn1c-gen/per_encoder.h
new file mode 100644
index 000000000000..95a6506e47b5
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/per_encoder.h
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2006, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_PER_ENCODER_H_
+#define	_PER_ENCODER_H_
+
+#include <asn_application.h>
+#include <per_support.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;	/* Forward declaration */
+
+/*
+ * Unaligned PER encoder of any ASN.1 type. May be invoked by the application.
+ * WARNING: This function returns the number of encoded bits in the .encoded
+ * field of the return value. Use the following formula to convert to bytes:
+ * 	bytes = ((.encoded + 7) / 8)
+ */
+asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor,
+	void *struct_ptr,	/* Structure to be encoded */
+	asn_app_consume_bytes_f *consume_bytes_cb,	/* Data collector */
+	void *app_key		/* Arbitrary callback argument */
+);
+
+/*
+ * A variant of uper_encode() which encodes data into the existing buffer
+ * WARNING: This function returns the number of encoded bits in the .encoded
+ * field of the return value.
+ */
+asn_enc_rval_t uper_encode_to_buffer(
+	struct asn_TYPE_descriptor_s *type_descriptor,
+	void *struct_ptr,	/* Structure to be encoded */
+	void *buffer,		/* Pre-allocated buffer */
+	size_t buffer_size	/* Initial buffer size (max) */
+);
+
+/*
+ * A variant of uper_encode_to_buffer() which allocates buffer itself.
+ * Returns the number of bytes in the buffer or -1 in case of failure.
+ * WARNING: This function produces a "Production of the complete encoding",
+ * with length of at least one octet. Contrast this to precise bit-packing
+ * encoding of uper_encode() and uper_encode_to_buffer().
+ */
+ssize_t uper_encode_to_new_buffer(
+	struct asn_TYPE_descriptor_s *type_descriptor,
+	asn_per_constraints_t *constraints,
+	void *struct_ptr,	/* Structure to be encoded */
+	void **buffer_r		/* Buffer allocated and returned */
+);
+
+/*
+ * Type of the generic PER encoder function.
+ */
+typedef asn_enc_rval_t (per_type_encoder_f)(
+	struct asn_TYPE_descriptor_s *type_descriptor,
+	asn_per_constraints_t *constraints,
+	void *struct_ptr,
+	asn_per_outp_t *per_output
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _PER_ENCODER_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/per_opentype.c b/libkmod/pkcs7/asn1c-gen/per_opentype.c
new file mode 100644
index 000000000000..404aa7264555
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/per_opentype.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <per_support.h>
+#include <constr_TYPE.h>
+#include <per_opentype.h>
+
+typedef struct uper_ugot_key {
+	asn_per_data_t oldpd;	/* Old per data source */
+	size_t unclaimed;
+	size_t ot_moved;	/* Number of bits moved by OT processing */
+	int repeat;
+} uper_ugot_key;
+
+static int uper_ugot_refill(asn_per_data_t *pd);
+static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
+static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t *, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
+
+/*
+ * Encode an "open type field".
+ * #10.1, #10.2
+ */
+int
+uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+	void *buf;
+	void *bptr;
+	ssize_t size;
+	size_t toGo;
+
+	ASN_DEBUG("Open type put %s ...", td->name);
+
+	size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
+	if(size <= 0) return -1;
+
+	for(bptr = buf, toGo = size; toGo;) {
+		ssize_t maySave = uper_put_length(po, toGo);
+		ASN_DEBUG("Prepending length %d to %s and allowing to save %d",
+			(int)size, td->name, (int)maySave);
+		if(maySave < 0) break;
+		if(per_put_many_bits(po, bptr, maySave * 8)) break;
+		bptr = (char *)bptr + maySave;
+		toGo -= maySave;
+	}
+
+	FREEMEM(buf);
+	if(toGo) return -1;
+
+	ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
+		td->name, (long)size);
+
+	return 0;
+}
+
+static asn_dec_rval_t
+uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+	asn_dec_rval_t rv;
+	ssize_t chunk_bytes;
+	int repeat;
+	uint8_t *buf = 0;
+	size_t bufLen = 0;
+	size_t bufSize = 0;
+	asn_per_data_t spd;
+	size_t padding;
+
+	ASN__STACK_OVERFLOW_CHECK(ctx);
+
+	ASN_DEBUG("Getting open type %s...", td->name);
+
+	do {
+		chunk_bytes = uper_get_length(pd, -1, &repeat);
+		if(chunk_bytes < 0) {
+			FREEMEM(buf);
+			ASN__DECODE_STARVED;
+		}
+		if(bufLen + chunk_bytes > bufSize) {
+			void *ptr;
+			bufSize = chunk_bytes + (bufSize << 2);
+			ptr = REALLOC(buf, bufSize);
+			if(!ptr) {
+				FREEMEM(buf);
+				ASN__DECODE_FAILED;
+			}
+			buf = ptr;
+		}
+		if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
+			FREEMEM(buf);
+			ASN__DECODE_STARVED;
+		}
+		bufLen += chunk_bytes;
+	} while(repeat);
+
+	ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
+		(long)bufLen);
+
+	memset(&spd, 0, sizeof(spd));
+	spd.buffer = buf;
+	spd.nbits = bufLen << 3;
+
+	ASN_DEBUG_INDENT_ADD(+4);
+	rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
+	ASN_DEBUG_INDENT_ADD(-4);
+
+	if(rv.code == RC_OK) {
+		/* Check padding validity */
+		padding = spd.nbits - spd.nboff;
+                if ((padding < 8 ||
+		/* X.691#10.1.3 */
+		(spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
+                    per_get_few_bits(&spd, padding) == 0) {
+			/* Everything is cool */
+			FREEMEM(buf);
+			return rv;
+		}
+		FREEMEM(buf);
+		if(padding >= 8) {
+			ASN_DEBUG("Too large padding %d in open type", (int)padding);
+			ASN__DECODE_FAILED;
+		} else {
+			ASN_DEBUG("Non-zero padding");
+			ASN__DECODE_FAILED;
+		}
+	} else {
+		FREEMEM(buf);
+		/* rv.code could be RC_WMORE, nonsense in this context */
+		rv.code = RC_FAIL; /* Noone would give us more */
+	}
+
+	return rv;
+}
+
+static asn_dec_rval_t GCC_NOTUSED
+uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+	uper_ugot_key arg;
+	asn_dec_rval_t rv;
+	ssize_t padding;
+
+	ASN__STACK_OVERFLOW_CHECK(ctx);
+
+	ASN_DEBUG("Getting open type %s from %s", td->name,
+		per_data_string(pd));
+	arg.oldpd = *pd;
+	arg.unclaimed = 0;
+	arg.ot_moved = 0;
+	arg.repeat = 1;
+	pd->refill = uper_ugot_refill;
+	pd->refill_key = &arg;
+	pd->nbits = pd->nboff;	/* 0 good bits at this point, will refill */
+	pd->moved = 0;	/* This now counts the open type size in bits */
+
+	ASN_DEBUG_INDENT_ADD(+4);
+	rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
+	ASN_DEBUG_INDENT_ADD(-4);
+
+#define	UPDRESTOREPD	do {						\
+	/* buffer and nboff are valid, preserve them. */		\
+	pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved);	\
+	pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved);	\
+	pd->refill = arg.oldpd.refill;					\
+	pd->refill_key = arg.oldpd.refill_key;				\
+  } while(0)
+
+	if(rv.code != RC_OK) {
+		UPDRESTOREPD;
+		return rv;
+	}
+
+	ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
+		per_data_string(pd),
+		per_data_string(&arg.oldpd),
+		(int)arg.unclaimed, (int)arg.repeat);
+
+	padding = pd->moved % 8;
+	if(padding) {
+		int32_t pvalue;
+		if(padding > 7) {
+			ASN_DEBUG("Too large padding %d in open type",
+				(int)padding);
+			rv.code = RC_FAIL;
+			UPDRESTOREPD;
+			return rv;
+		}
+		padding = 8 - padding;
+		ASN_DEBUG("Getting padding of %d bits", (int)padding);
+		pvalue = per_get_few_bits(pd, padding);
+		switch(pvalue) {
+		case -1:
+			ASN_DEBUG("Padding skip failed");
+			UPDRESTOREPD;
+			ASN__DECODE_STARVED;
+		case 0: break;
+		default:
+			ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
+				(int)padding, (int)pvalue);
+			UPDRESTOREPD;
+			ASN__DECODE_FAILED;
+		}
+	}
+	if(pd->nboff != pd->nbits) {
+		ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
+			per_data_string(pd), per_data_string(&arg.oldpd));
+		if(1) {
+			UPDRESTOREPD;
+			ASN__DECODE_FAILED;
+		} else {
+			arg.unclaimed += pd->nbits - pd->nboff;
+		}
+	}
+
+	/* Adjust pd back so it points to original data */
+	UPDRESTOREPD;
+
+	/* Skip data not consumed by the decoder */
+	if(arg.unclaimed) {
+		ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
+		switch(per_skip_bits(pd, arg.unclaimed)) {
+		case -1:
+			ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
+			ASN__DECODE_STARVED;
+		case 0:
+			ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
+			break;
+		default:
+			/* Padding must be blank */
+			ASN_DEBUG("Non-blank unconsumed padding");
+			ASN__DECODE_FAILED;
+		}
+		arg.unclaimed = 0;
+	}
+
+	if(arg.repeat) {
+		ASN_DEBUG("Not consumed the whole thing");
+		rv.code = RC_FAIL;
+		return rv;
+	}
+
+	return rv;
+}
+
+
+asn_dec_rval_t
+uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+
+	return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
+}
+
+int
+uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
+	asn_TYPE_descriptor_t s_td;
+	asn_dec_rval_t rv;
+
+	s_td.name = "<unknown extension>";
+	s_td.uper_decoder = uper_sot_suck;
+
+	rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
+	if(rv.code != RC_OK)
+		return -1;
+	else
+		return 0;
+}
+
+/*
+ * Internal functions.
+ */
+
+static asn_dec_rval_t
+uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
+	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+	asn_dec_rval_t rv;
+
+	(void)ctx;
+	(void)td;
+	(void)constraints;
+	(void)sptr;
+
+	while(per_get_few_bits(pd, 24) >= 0);
+
+	rv.code = RC_OK;
+	rv.consumed = pd->moved;
+
+	return rv;
+}
+
+static int
+uper_ugot_refill(asn_per_data_t *pd) {
+	uper_ugot_key *arg = pd->refill_key;
+	ssize_t next_chunk_bytes, next_chunk_bits;
+	ssize_t avail;
+
+	asn_per_data_t *oldpd = &arg->oldpd;
+
+	ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
+		(long)pd->moved, (long)oldpd->moved);
+
+	/* Advance our position to where pd is */
+	oldpd->buffer = pd->buffer;
+	oldpd->nboff  = pd->nboff;
+	oldpd->nbits -= pd->moved - arg->ot_moved;
+	oldpd->moved += pd->moved - arg->ot_moved;
+	arg->ot_moved = pd->moved;
+
+	if(arg->unclaimed) {
+		/* Refill the container */
+		if(per_get_few_bits(oldpd, 1))
+			return -1;
+		if(oldpd->nboff == 0) {
+			assert(0);
+			return -1;
+		}
+		pd->buffer = oldpd->buffer;
+		pd->nboff = oldpd->nboff - 1;
+		pd->nbits = oldpd->nbits;
+		ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
+			(long)pd->moved);
+		return 0;
+	}
+
+	if(!arg->repeat) {
+		ASN_DEBUG("Want more but refill doesn't have it");
+		return -1;
+	}
+
+	next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
+	ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
+		(long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
+	if(next_chunk_bytes < 0) return -1;
+	if(next_chunk_bytes == 0) {
+		pd->refill = 0;	/* No more refills, naturally */
+		assert(!arg->repeat);	/* Implementation guarantee */
+	}
+	next_chunk_bits = next_chunk_bytes << 3;
+	avail = oldpd->nbits - oldpd->nboff;
+	if(avail >= next_chunk_bits) {
+		pd->nbits = oldpd->nboff + next_chunk_bits;
+		arg->unclaimed = 0;
+		ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
+			(long)next_chunk_bits, (long)oldpd->moved,
+			(long)oldpd->nboff, (long)oldpd->nbits,
+			(long)(oldpd->nbits - oldpd->nboff));
+	} else {
+		pd->nbits = oldpd->nbits;
+		arg->unclaimed = next_chunk_bits - avail;
+		ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
+			(long)avail, (long)next_chunk_bits,
+			(long)arg->unclaimed);
+	}
+	pd->buffer = oldpd->buffer;
+	pd->nboff = oldpd->nboff;
+	ASN_DEBUG("Refilled pd%s old%s",
+		per_data_string(pd), per_data_string(oldpd));
+	return 0;
+}
+
+static int
+per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
+	int hasNonZeroBits = 0;
+	while(skip_nbits > 0) {
+		int skip;
+
+		/* per_get_few_bits() is more efficient when nbits <= 24 */
+		if(skip_nbits < 24)
+			skip = skip_nbits;
+		else
+			skip = 24;
+		skip_nbits -= skip;
+
+		switch(per_get_few_bits(pd, skip)) {
+		case -1: return -1;	/* Starving */
+		case 0: continue;	/* Skipped empty space */
+		default: hasNonZeroBits = 1; continue;
+		}
+	}
+	return hasNonZeroBits;
+}
diff --git a/libkmod/pkcs7/asn1c-gen/per_opentype.h b/libkmod/pkcs7/asn1c-gen/per_opentype.h
new file mode 100644
index 000000000000..facfaa6377bd
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/per_opentype.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_PER_OPENTYPE_H_
+#define	_PER_OPENTYPE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+asn_dec_rval_t uper_open_type_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
+
+int uper_open_type_skip(asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd);
+
+int uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _PER_OPENTYPE_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/per_support.c b/libkmod/pkcs7/asn1c-gen/per_support.c
new file mode 100644
index 000000000000..14b4c4c76be0
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/per_support.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2005-2014 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_system.h>
+#include <asn_internal.h>
+#include <per_support.h>
+
+char *
+per_data_string(asn_per_data_t *pd) {
+	static char buf[2][32];
+	static int n;
+	n = (n+1) % 2;
+	snprintf(buf[n], sizeof(buf[n]),
+		"{m=%ld span %+ld[%d..%d] (%d)}",
+		(long)pd->moved,
+		(((long)pd->buffer) & 0xf),
+		(int)pd->nboff, (int)pd->nbits,
+		(int)(pd->nbits - pd->nboff));
+	return buf[n];
+}
+
+void
+per_get_undo(asn_per_data_t *pd, int nbits) {
+	if((ssize_t)pd->nboff < nbits) {
+		assert((ssize_t)pd->nboff < nbits);
+	} else {
+		pd->nboff -= nbits;
+		pd->moved -= nbits;
+	}
+}
+
+/*
+ * Extract a small number of bits (<= 31) from the specified PER data pointer.
+ */
+int32_t
+per_get_few_bits(asn_per_data_t *pd, int nbits) {
+	size_t off;	/* Next after last bit offset */
+	ssize_t nleft;	/* Number of bits left in this stream */
+	uint32_t accum;
+	const uint8_t *buf;
+
+	if(nbits < 0)
+		return -1;
+
+	nleft = pd->nbits - pd->nboff;
+	if(nbits > nleft) {
+		int32_t tailv, vhead;
+		if(!pd->refill || nbits > 31) return -1;
+		/* Accumulate unused bytes before refill */
+		ASN_DEBUG("Obtain the rest %d bits (want %d)",
+			(int)nleft, (int)nbits);
+		tailv = per_get_few_bits(pd, nleft);
+		if(tailv < 0) return -1;
+		/* Refill (replace pd contents with new data) */
+		if(pd->refill(pd))
+			return -1;
+		nbits -= nleft;
+		vhead = per_get_few_bits(pd, nbits);
+		/* Combine the rest of previous pd with the head of new one */
+		tailv = (tailv << nbits) | vhead;  /* Could == -1 */
+		return tailv;
+	}
+
+	/*
+	 * Normalize position indicator.
+	 */
+	if(pd->nboff >= 8) {
+		pd->buffer += (pd->nboff >> 3);
+		pd->nbits  -= (pd->nboff & ~0x07);
+		pd->nboff  &= 0x07;
+	}
+	pd->moved += nbits;
+	pd->nboff += nbits;
+	off = pd->nboff;
+	buf = pd->buffer;
+
+	/*
+	 * Extract specified number of bits.
+	 */
+	if(off <= 8)
+		accum = nbits ? (buf[0]) >> (8 - off) : 0;
+	else if(off <= 16)
+		accum = ((buf[0] << 8) + buf[1]) >> (16 - off);
+	else if(off <= 24)
+		accum = ((buf[0] << 16) + (buf[1] << 8) + buf[2]) >> (24 - off);
+	else if(off <= 31)
+		accum = ((buf[0] << 24) + (buf[1] << 16)
+			+ (buf[2] << 8) + (buf[3])) >> (32 - off);
+	else if(nbits <= 31) {
+		asn_per_data_t tpd = *pd;
+		/* Here are we with our 31-bits limit plus 1..7 bits offset. */
+		per_get_undo(&tpd, nbits);
+		/* The number of available bits in the stream allow
+		 * for the following operations to take place without
+		 * invoking the ->refill() function */
+		accum  = per_get_few_bits(&tpd, nbits - 24) << 24;
+		accum |= per_get_few_bits(&tpd, 24);
+	} else {
+		per_get_undo(pd, nbits);
+		return -1;
+	}
+
+	accum &= (((uint32_t)1 << nbits) - 1);
+
+	ASN_DEBUG("  [PER got %2d<=%2d bits => span %d %+ld[%d..%d]:%02x (%d) => 0x%x]",
+		(int)nbits, (int)nleft,
+		(int)pd->moved,
+		(((long)pd->buffer) & 0xf),
+		(int)pd->nboff, (int)pd->nbits,
+		((pd->buffer != NULL)?pd->buffer[0]:0),
+		(int)(pd->nbits - pd->nboff),
+		(int)accum);
+
+	return accum;
+}
+
+/*
+ * Extract a large number of bits from the specified PER data pointer.
+ */
+int
+per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int alright, int nbits) {
+	int32_t value;
+
+	if(alright && (nbits & 7)) {
+		/* Perform right alignment of a first few bits */
+		value = per_get_few_bits(pd, nbits & 0x07);
+		if(value < 0) return -1;
+		*dst++ = value;	/* value is already right-aligned */
+		nbits &= ~7;
+	}
+
+	while(nbits) {
+		if(nbits >= 24) {
+			value = per_get_few_bits(pd, 24);
+			if(value < 0) return -1;
+			*(dst++) = value >> 16;
+			*(dst++) = value >> 8;
+			*(dst++) = value;
+			nbits -= 24;
+		} else {
+			value = per_get_few_bits(pd, nbits);
+			if(value < 0) return -1;
+			if(nbits & 7) {	/* implies left alignment */
+				value <<= 8 - (nbits & 7),
+				nbits += 8 - (nbits & 7);
+				if(nbits > 24)
+					*dst++ = value >> 24;
+			}
+			if(nbits > 16)
+				*dst++ = value >> 16;
+			if(nbits > 8)
+				*dst++ = value >> 8;
+			*dst++ = value;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Get the length "n" from the stream.
+ */
+ssize_t
+uper_get_length(asn_per_data_t *pd, int ebits, int *repeat) {
+	ssize_t value;
+
+	*repeat = 0;
+
+	if(ebits >= 0) return per_get_few_bits(pd, ebits);
+
+	value = per_get_few_bits(pd, 8);
+	if(value < 0) return -1;
+	if((value & 128) == 0)	/* #10.9.3.6 */
+		return (value & 0x7F);
+	if((value & 64) == 0) {	/* #10.9.3.7 */
+		value = ((value & 63) << 8) | per_get_few_bits(pd, 8);
+		if(value < 0) return -1;
+		return value;
+	}
+	value &= 63;	/* this is "m" from X.691, #10.9.3.8 */
+	if(value < 1 || value > 4)
+		return -1;
+	*repeat = 1;
+	return (16384 * value);
+}
+
+/*
+ * Get the normally small length "n".
+ * This procedure used to decode length of extensions bit-maps
+ * for SET and SEQUENCE types.
+ */
+ssize_t
+uper_get_nslength(asn_per_data_t *pd) {
+	ssize_t length;
+
+	ASN_DEBUG("Getting normally small length");
+
+	if(per_get_few_bits(pd, 1) == 0) {
+		length = per_get_few_bits(pd, 6) + 1;
+		if(length <= 0) return -1;
+		ASN_DEBUG("l=%d", (int)length);
+		return length;
+	} else {
+		int repeat;
+		length = uper_get_length(pd, -1, &repeat);
+		if(length >= 0 && !repeat) return length;
+		return -1; /* Error, or do not support >16K extensions */
+	}
+}
+
+/*
+ * Get the normally small non-negative whole number.
+ * X.691, #10.6
+ */
+ssize_t
+uper_get_nsnnwn(asn_per_data_t *pd) {
+	ssize_t value;
+
+	value = per_get_few_bits(pd, 7);
+	if(value & 64) {	/* implicit (value < 0) */
+		value &= 63;
+		value <<= 2;
+		value |= per_get_few_bits(pd, 2);
+		if(value & 128)	/* implicit (value < 0) */
+			return -1;
+		if(value == 0)
+			return 0;
+		if(value >= 3)
+			return -1;
+		value = per_get_few_bits(pd, 8 * value);
+		return value;
+	}
+
+	return value;
+}
+
+/*
+ * X.691-11/2008, #11.6
+ * Encoding of a normally small non-negative whole number
+ */
+int
+uper_put_nsnnwn(asn_per_outp_t *po, int n) {
+	int bytes;
+
+	if(n <= 63) {
+		if(n < 0) return -1;
+		return per_put_few_bits(po, n, 7);
+	}
+	if(n < 256)
+		bytes = 1;
+	else if(n < 65536)
+		bytes = 2;
+	else if(n < 256 * 65536)
+		bytes = 3;
+	else
+		return -1;	/* This is not a "normally small" value */
+	if(per_put_few_bits(po, bytes, 8))
+		return -1;
+
+	return per_put_few_bits(po, n, 8 * bytes);
+}
+
+
+/* X.691-2008/11, #11.5.6 -> #11.3 */
+int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *out_value, int nbits) {
+	unsigned long lhalf;    /* Lower half of the number*/
+	long half;
+
+	if(nbits <= 31) {
+		half = per_get_few_bits(pd, nbits);
+		if(half < 0) return -1;
+		*out_value = half;
+		return 0;
+	}
+
+	if((size_t)nbits > 8 * sizeof(*out_value))
+		return -1;  /* RANGE */
+
+	half = per_get_few_bits(pd, 31);
+	if(half < 0) return -1;
+
+	if(uper_get_constrained_whole_number(pd, &lhalf, nbits - 31))
+		return -1;
+
+	*out_value = ((unsigned long)half << (nbits - 31)) | lhalf;
+	return 0;
+}
+
+
+/* X.691-2008/11, #11.5.6 -> #11.3 */
+int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits) {
+	/*
+	 * Assume signed number can be safely coerced into
+	 * unsigned of the same range.
+	 * The following testing code will likely be optimized out
+	 * by compiler if it is true.
+	 */
+	unsigned long uvalue1 = ULONG_MAX;
+	         long svalue  = uvalue1;
+	unsigned long uvalue2 = svalue;
+	assert(uvalue1 == uvalue2);
+	return uper_put_constrained_whole_number_u(po, v, nbits);
+}
+
+int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits) {
+	if(nbits <= 31) {
+		return per_put_few_bits(po, v, nbits);
+	} else {
+		/* Put higher portion first, followed by lower 31-bit */
+		if(uper_put_constrained_whole_number_u(po, v >> 31, nbits - 31))
+			return -1;
+		return per_put_few_bits(po, v, 31);
+	}
+}
+
+/*
+ * Put a small number of bits (<= 31).
+ */
+int
+per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
+	size_t off;	/* Next after last bit offset */
+	size_t omsk;	/* Existing last byte meaningful bits mask */
+	uint8_t *buf;
+
+	if(obits <= 0 || obits >= 32) return obits ? -1 : 0;
+
+	ASN_DEBUG("[PER put %d bits %x to %p+%d bits]",
+			obits, (int)bits, po->buffer, (int)po->nboff);
+
+	/*
+	 * Normalize position indicator.
+	 */
+	if(po->nboff >= 8) {
+		po->buffer += (po->nboff >> 3);
+		po->nbits  -= (po->nboff & ~0x07);
+		po->nboff  &= 0x07;
+	}
+
+	/*
+	 * Flush whole-bytes output, if necessary.
+	 */
+	if(po->nboff + obits > po->nbits) {
+		int complete_bytes = (po->buffer - po->tmpspace);
+		ASN_DEBUG("[PER output %ld complete + %ld]",
+			(long)complete_bytes, (long)po->flushed_bytes);
+		if(po->outper(po->tmpspace, complete_bytes, po->op_key) < 0)
+			return -1;
+		if(po->nboff)
+			po->tmpspace[0] = po->buffer[0];
+		po->buffer = po->tmpspace;
+		po->nbits = 8 * sizeof(po->tmpspace);
+		po->flushed_bytes += complete_bytes;
+	}
+
+	/*
+	 * Now, due to sizeof(tmpspace), we are guaranteed large enough space.
+	 */
+	buf = po->buffer;
+	omsk = ~((1 << (8 - po->nboff)) - 1);
+	off = (po->nboff + obits);
+
+	/* Clear data of debris before meaningful bits */
+	bits &= (((uint32_t)1 << obits) - 1);
+
+	ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits,
+		(int)bits, (int)bits,
+		(int)po->nboff, (int)off,
+		buf[0], (int)(omsk&0xff),
+		(int)(buf[0] & omsk));
+
+	if(off <= 8)	/* Completely within 1 byte */
+		po->nboff = off,
+		bits <<= (8 - off),
+		buf[0] = (buf[0] & omsk) | bits;
+	else if(off <= 16)
+		po->nboff = off,
+		bits <<= (16 - off),
+		buf[0] = (buf[0] & omsk) | (bits >> 8),
+		buf[1] = bits;
+	else if(off <= 24)
+		po->nboff = off,
+		bits <<= (24 - off),
+		buf[0] = (buf[0] & omsk) | (bits >> 16),
+		buf[1] = bits >> 8,
+		buf[2] = bits;
+	else if(off <= 31)
+		po->nboff = off,
+		bits <<= (32 - off),
+		buf[0] = (buf[0] & omsk) | (bits >> 24),
+		buf[1] = bits >> 16,
+		buf[2] = bits >> 8,
+		buf[3] = bits;
+	else {
+		per_put_few_bits(po, bits >> (obits - 24), 24);
+		per_put_few_bits(po, bits, obits - 24);
+	}
+
+	ASN_DEBUG("[PER out %u/%x => %02x buf+%ld]",
+		(int)bits, (int)bits, buf[0],
+		(long)(po->buffer - po->tmpspace));
+
+	return 0;
+}
+
+
+/*
+ * Output a large number of bits.
+ */
+int
+per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int nbits) {
+
+	while(nbits) {
+		uint32_t value;
+
+		if(nbits >= 24) {
+			value = (src[0] << 16) | (src[1] << 8) | src[2];
+			src += 3;
+			nbits -= 24;
+			if(per_put_few_bits(po, value, 24))
+				return -1;
+		} else {
+			value = src[0];
+			if(nbits > 8)
+				value = (value << 8) | src[1];
+			if(nbits > 16)
+				value = (value << 8) | src[2];
+			if(nbits & 0x07)
+				value >>= (8 - (nbits & 0x07));
+			if(per_put_few_bits(po, value, nbits))
+				return -1;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Put the length "n" (or part of it) into the stream.
+ */
+ssize_t
+uper_put_length(asn_per_outp_t *po, size_t length) {
+
+	if(length <= 127)	/* #10.9.3.6 */
+		return per_put_few_bits(po, length, 8)
+			? -1 : (ssize_t)length;
+	else if(length < 16384)	/* #10.9.3.7 */
+		return per_put_few_bits(po, length|0x8000, 16)
+			? -1 : (ssize_t)length;
+
+	length >>= 14;
+	if(length > 4) length = 4;
+
+	return per_put_few_bits(po, 0xC0 | length, 8)
+			? -1 : (ssize_t)(length << 14);
+}
+
+
+/*
+ * Put the normally small length "n" into the stream.
+ * This procedure used to encode length of extensions bit-maps
+ * for SET and SEQUENCE types.
+ */
+int
+uper_put_nslength(asn_per_outp_t *po, size_t length) {
+
+	if(length <= 64) {
+		/* #10.9.3.4 */
+		if(length == 0) return -1;
+		return per_put_few_bits(po, length-1, 7) ? -1 : 0;
+	} else {
+		if(uper_put_length(po, length) != (ssize_t)length) {
+			/* This might happen in case of >16K extensions */
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/per_support.h b/libkmod/pkcs7/asn1c-gen/per_support.h
new file mode 100644
index 000000000000..a75ac94fc4a9
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/per_support.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2005-2014 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_PER_SUPPORT_H_
+#define	_PER_SUPPORT_H_
+
+#include <asn_system.h>		/* Platform-specific types */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Pre-computed PER constraints.
+ */
+typedef const struct asn_per_constraint_s {
+	enum asn_per_constraint_flags {
+		APC_UNCONSTRAINED	= 0x0,	/* No PER visible constraints */
+		APC_SEMI_CONSTRAINED	= 0x1,	/* Constrained at "lb" */
+		APC_CONSTRAINED		= 0x2,	/* Fully constrained */
+		APC_EXTENSIBLE		= 0x4	/* May have extension */
+	} flags;
+	int  range_bits;		/* Full number of bits in the range */
+	int  effective_bits;		/* Effective bits */
+	long lower_bound;		/* "lb" value */
+	long upper_bound;		/* "ub" value */
+} asn_per_constraint_t;
+typedef const struct asn_per_constraints_s {
+	struct asn_per_constraint_s value;
+	struct asn_per_constraint_s size;
+	int (*value2code)(unsigned int value);
+	int (*code2value)(unsigned int code);
+} asn_per_constraints_t;
+
+/*
+ * This structure describes a position inside an incoming PER bit stream.
+ */
+typedef struct asn_per_data_s {
+  const uint8_t *buffer;  /* Pointer to the octet stream */
+         size_t  nboff;   /* Bit offset to the meaningful bit */
+         size_t  nbits;   /* Number of bits in the stream */
+         size_t  moved;   /* Number of bits moved through this bit stream */
+  int (*refill)(struct asn_per_data_s *);
+  void *refill_key;
+} asn_per_data_t;
+
+/*
+ * Extract a small number of bits (<= 31) from the specified PER data pointer.
+ * This function returns -1 if the specified number of bits could not be
+ * extracted due to EOD or other conditions.
+ */
+int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits);
+
+/* Undo the immediately preceeding "get_few_bits" operation */
+void per_get_undo(asn_per_data_t *per_data, int get_nbits);
+
+/*
+ * Extract a large number of bits from the specified PER data pointer.
+ * This function returns -1 if the specified number of bits could not be
+ * extracted due to EOD or other conditions.
+ */
+int per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int right_align,
+			int get_nbits);
+
+/*
+ * Get the length "n" from the Unaligned PER stream.
+ */
+ssize_t uper_get_length(asn_per_data_t *pd,
+			int effective_bound_bits,
+			int *repeat);
+
+/*
+ * Get the normally small length "n".
+ */
+ssize_t uper_get_nslength(asn_per_data_t *pd);
+
+/*
+ * Get the normally small non-negative whole number.
+ */
+ssize_t uper_get_nsnnwn(asn_per_data_t *pd);
+
+/* X.691-2008/11, #11.5.6 */
+int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *v, int nbits);
+
+/* Non-thread-safe debugging function, don't use it */
+char *per_data_string(asn_per_data_t *pd);
+
+/*
+ * This structure supports forming PER output.
+ */
+typedef struct asn_per_outp_s {
+	uint8_t *buffer;	/* Pointer into the (tmpspace) */
+	size_t nboff;		/* Bit offset to the meaningful bit */
+	size_t nbits;		/* Number of bits left in (tmpspace) */
+	uint8_t tmpspace[32];	/* Preliminary storage to hold data */
+	int (*outper)(const void *data, size_t size, void *op_key);
+	void *op_key;		/* Key for (outper) data callback */
+	size_t flushed_bytes;	/* Bytes already flushed through (outper) */
+} asn_per_outp_t;
+
+/* Output a small number of bits (<= 31) */
+int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits);
+
+/* Output a large number of bits */
+int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits);
+
+/* X.691-2008/11, #11.5 */
+int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits);
+int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits);
+
+/*
+ * Put the length "n" to the Unaligned PER stream.
+ * This function returns the number of units which may be flushed
+ * in the next units saving iteration.
+ */
+ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length);
+
+/*
+ * Put the normally small length "n" to the Unaligned PER stream.
+ * Returns 0 or -1.
+ */
+int uper_put_nslength(asn_per_outp_t *po, size_t length);
+
+/*
+ * Put the normally small non-negative whole number.
+ */
+int uper_put_nsnnwn(asn_per_outp_t *po, int n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _PER_SUPPORT_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/xer_decoder.c b/libkmod/pkcs7/asn1c-gen/xer_decoder.c
new file mode 100644
index 000000000000..299a7c1eed8a
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/xer_decoder.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_application.h>
+#include <asn_internal.h>
+#include <xer_support.h>		/* XER/XML parsing support */
+
+
+/*
+ * Decode the XER encoding of a given type.
+ */
+asn_dec_rval_t
+xer_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+		void **struct_ptr, const void *buffer, size_t size) {
+	asn_codec_ctx_t s_codec_ctx;
+
+	/*
+	 * Stack checker requires that the codec context
+	 * must be allocated on the stack.
+	 */
+	if(opt_codec_ctx) {
+		if(opt_codec_ctx->max_stack_size) {
+			s_codec_ctx = *opt_codec_ctx;
+			opt_codec_ctx = &s_codec_ctx;
+		}
+	} else {
+		/* If context is not given, be security-conscious anyway */
+		memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
+		s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
+		opt_codec_ctx = &s_codec_ctx;
+	}
+
+	/*
+	 * Invoke type-specific decoder.
+	 */
+	return td->xer_decoder(opt_codec_ctx, td, struct_ptr, 0, buffer, size);
+}
+
+
+
+struct xer__cb_arg {
+	pxml_chunk_type_e	chunk_type;
+	size_t			chunk_size;
+	const void		*chunk_buf;
+	int callback_not_invoked;
+};
+
+static int
+xer__token_cb(pxml_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key) {
+	struct xer__cb_arg *arg = (struct xer__cb_arg *)key;
+	arg->chunk_type = type;
+	arg->chunk_size = _chunk_size;
+	arg->chunk_buf = _chunk_data;
+	arg->callback_not_invoked = 0;
+	return -1;	/* Terminate the XML parsing */
+}
+
+/*
+ * Fetch the next token from the XER/XML stream.
+ */
+ssize_t
+xer_next_token(int *stateContext, const void *buffer, size_t size, pxer_chunk_type_e *ch_type) {
+	struct xer__cb_arg arg;
+	int new_stateContext = *stateContext;
+	ssize_t ret;
+
+	arg.callback_not_invoked = 1;
+	ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg);
+	if(ret < 0) return -1;
+	if(arg.callback_not_invoked) {
+		assert(ret == 0);	/* No data was consumed */
+        *ch_type = PXER_WMORE;
+		return 0;		/* Try again with more data */
+	} else {
+		assert(arg.chunk_size);
+		assert(arg.chunk_buf == buffer);
+	}
+
+	/*
+	 * Translate the XML chunk types into more convenient ones.
+	 */
+	switch(arg.chunk_type) {
+	case PXML_TEXT:
+		*ch_type = PXER_TEXT;
+		break;
+	case PXML_TAG:
+        *ch_type = PXER_WMORE;
+        return 0;	/* Want more */
+	case PXML_TAG_END:
+		*ch_type = PXER_TAG;
+		break;
+	case PXML_COMMENT:
+	case PXML_COMMENT_END:
+		*ch_type = PXER_COMMENT;
+		break;
+	}
+
+	*stateContext = new_stateContext;
+	return arg.chunk_size;
+}
+
+#define	CSLASH	0x2f	/* '/' */
+#define	LANGLE	0x3c	/* '<' */
+#define	RANGLE	0x3e	/* '>' */
+
+xer_check_tag_e
+xer_check_tag(const void *buf_ptr, int size, const char *need_tag) {
+	const char *buf = (const char *)buf_ptr;
+	const char *end;
+	xer_check_tag_e ct = XCT_OPENING;
+
+	if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) {
+		if(size >= 2)
+			ASN_DEBUG("Broken XML tag: \"%c...%c\"",
+			buf[0], buf[size - 1]);
+		return XCT_BROKEN;
+	}
+
+	/*
+	 * Determine the tag class.
+	 */
+	if(buf[1] == CSLASH) {
+		buf += 2;	/* advance past "</" */
+		size -= 3;	/* strip "</" and ">" */
+		ct = XCT_CLOSING;
+		if(size > 0 && buf[size-1] == CSLASH)
+			return XCT_BROKEN;	/* </abc/> */
+	} else {
+		buf++;		/* advance past "<" */
+		size -= 2;	/* strip "<" and ">" */
+		if(size > 0 && buf[size-1] == CSLASH) {
+			ct = XCT_BOTH;
+			size--;	/* One more, for "/" */
+		}
+	}
+
+	/* Sometimes we don't care about the tag */
+	if(!need_tag || !*need_tag)
+		return (xer_check_tag_e)(XCT__UNK__MASK | ct);
+
+	/*
+	 * Determine the tag name.
+	 */
+	for(end = buf + size; buf < end; buf++, need_tag++) {
+		int b = *buf, n = *need_tag;
+		if(b != n) {
+			if(n == 0) {
+				switch(b) {
+				case 0x09: case 0x0a: case 0x0c: case 0x0d:
+				case 0x20:
+					/* "<abc def/>": whitespace is normal */
+					return ct;
+				}
+			}
+			return (xer_check_tag_e)(XCT__UNK__MASK | ct);
+		}
+		if(b == 0)
+			return XCT_BROKEN;	/* Embedded 0 in buf?! */
+	}
+	if(*need_tag)
+		return (xer_check_tag_e)(XCT__UNK__MASK | ct);
+
+	return ct;
+}
+
+
+#undef	ADVANCE
+#define	ADVANCE(num_bytes)	do {				\
+		size_t num = (num_bytes);			\
+		buf_ptr = ((const char *)buf_ptr) + num;	\
+		size -= num;					\
+		consumed_myself += num;				\
+	} while(0)
+
+#undef	RETURN
+#define	RETURN(_code)	do {					\
+		rval.code = _code;				\
+		rval.consumed = consumed_myself;		\
+		if(rval.code != RC_OK)				\
+			ASN_DEBUG("Failed with %d", rval.code);	\
+		return rval;					\
+	} while(0)
+
+#define	XER_GOT_BODY(chunk_buf, chunk_size, size)	do {	\
+		ssize_t converted_size = body_receiver		\
+			(struct_key, chunk_buf, chunk_size,	\
+				(size_t)chunk_size < size);	\
+		if(converted_size == -1) RETURN(RC_FAIL);	\
+		if(converted_size == 0				\
+			&& size == (size_t)chunk_size)		\
+			RETURN(RC_WMORE);			\
+		chunk_size = converted_size;			\
+	} while(0)
+#define	XER_GOT_EMPTY()	do {					\
+	if(body_receiver(struct_key, 0, 0, size > 0) == -1)	\
+			RETURN(RC_FAIL);			\
+	} while(0)
+
+/*
+ * Generalized function for decoding the primitive values.
+ */
+asn_dec_rval_t
+xer_decode_general(asn_codec_ctx_t *opt_codec_ctx,
+	asn_struct_ctx_t *ctx,	/* Type decoder context */
+	void *struct_key,
+	const char *xml_tag,	/* Expected XML tag */
+	const void *buf_ptr, size_t size,
+	int (*opt_unexpected_tag_decoder)
+		(void *struct_key, const void *chunk_buf, size_t chunk_size),
+	ssize_t (*body_receiver)
+		(void *struct_key, const void *chunk_buf, size_t chunk_size,
+			int have_more)
+	) {
+
+	asn_dec_rval_t rval;
+	ssize_t consumed_myself = 0;
+
+	(void)opt_codec_ctx;
+
+	/*
+	 * Phases of XER/XML processing:
+	 * Phase 0: Check that the opening tag matches our expectations.
+	 * Phase 1: Processing body and reacting on closing tag.
+	 */
+	if(ctx->phase > 1) RETURN(RC_FAIL);
+	for(;;) {
+		pxer_chunk_type_e ch_type;	/* XER chunk type */
+		ssize_t ch_size;		/* Chunk size */
+		xer_check_tag_e tcv;		/* Tag check value */
+
+		/*
+		 * Get the next part of the XML stream.
+		 */
+		ch_size = xer_next_token(&ctx->context, buf_ptr, size,
+			&ch_type);
+		if(ch_size == -1) {
+            RETURN(RC_FAIL);
+        } else {
+			switch(ch_type) {
+			case PXER_WMORE:
+                RETURN(RC_WMORE);
+			case PXER_COMMENT:		/* Got XML comment */
+				ADVANCE(ch_size);	/* Skip silently */
+				continue;
+			case PXER_TEXT:
+				if(ctx->phase == 0) {
+					/*
+					 * We have to ignore whitespace here,
+					 * but in order to be forward compatible
+					 * with EXTENDED-XER (EMBED-VALUES, #25)
+					 * any text is just ignored here.
+					 */
+				} else {
+					XER_GOT_BODY(buf_ptr, ch_size, size);
+				}
+				ADVANCE(ch_size);
+				continue;
+			case PXER_TAG:
+				break;	/* Check the rest down there */
+			}
+		}
+
+		assert(ch_type == PXER_TAG && size);
+
+		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
+		/*
+		 * Phase 0:
+		 * 	Expecting the opening tag
+		 * 	for the type being processed.
+		 * Phase 1:
+		 * 	Waiting for the closing XML tag.
+		 */
+		switch(tcv) {
+		case XCT_BOTH:
+			if(ctx->phase) break;
+			/* Finished decoding of an empty element */
+			XER_GOT_EMPTY();
+			ADVANCE(ch_size);
+			ctx->phase = 2;	/* Phase out */
+			RETURN(RC_OK);
+		case XCT_OPENING:
+			if(ctx->phase) break;
+			ADVANCE(ch_size);
+			ctx->phase = 1;	/* Processing body phase */
+			continue;
+		case XCT_CLOSING:
+			if(!ctx->phase) break;
+			ADVANCE(ch_size);
+			ctx->phase = 2;	/* Phase out */
+			RETURN(RC_OK);
+		case XCT_UNKNOWN_BO:
+			/*
+			 * Certain tags in the body may be expected.
+			 */
+			if(opt_unexpected_tag_decoder
+			&& opt_unexpected_tag_decoder(struct_key,
+					buf_ptr, ch_size) >= 0) {
+				/* Tag's processed fine */
+				ADVANCE(ch_size);
+				if(!ctx->phase) {
+					/* We are not expecting
+					 * the closing tag anymore. */
+					ctx->phase = 2;	/* Phase out */
+					RETURN(RC_OK);
+				}
+				continue;
+			}
+			/* Fall through */
+		default:
+			break;		/* Unexpected tag */
+		}
+
+		ASN_DEBUG("Unexpected XML tag (expected \"%s\")", xml_tag);
+		break;	/* Dark and mysterious things have just happened */
+	}
+
+	RETURN(RC_FAIL);
+}
+
+
+size_t
+xer_whitespace_span(const void *chunk_buf, size_t chunk_size) {
+	const char *p = (const char *)chunk_buf;
+	const char *pend = p + chunk_size;
+
+	for(; p < pend; p++) {
+		switch(*p) {
+		/* X.693, #8.1.4
+		 * HORISONTAL TAB (9)
+		 * LINE FEED (10) 
+		 * CARRIAGE RETURN (13) 
+		 * SPACE (32)
+		 */
+		case 0x09: case 0x0a: case 0x0d: case 0x20:
+			continue;
+		default:
+			break;
+		}
+		break;
+	}
+	return (p - (const char *)chunk_buf);
+}
+
+/*
+ * This is a vastly simplified, non-validating XML tree skipper.
+ */
+int
+xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth) {
+	assert(*depth > 0);
+	switch(tcv) {
+	case XCT_BOTH:
+	case XCT_UNKNOWN_BO:
+		/* These negate each other. */
+		return 0;
+	case XCT_OPENING:
+	case XCT_UNKNOWN_OP:
+		++(*depth);
+		return 0;
+	case XCT_CLOSING:
+	case XCT_UNKNOWN_CL:
+		if(--(*depth) == 0)
+			return (tcv == XCT_CLOSING) ? 2 : 1;
+		return 0;
+	default:
+		return -1;
+	}
+}
diff --git a/libkmod/pkcs7/asn1c-gen/xer_decoder.h b/libkmod/pkcs7/asn1c-gen/xer_decoder.h
new file mode 100644
index 000000000000..301b613cf4bd
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/xer_decoder.h
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_XER_DECODER_H_
+#define	_XER_DECODER_H_
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;	/* Forward declaration */
+
+/*
+ * The XER decoder of any ASN.1 type. May be invoked by the application.
+ */
+asn_dec_rval_t xer_decode(struct asn_codec_ctx_s *opt_codec_ctx,
+	struct asn_TYPE_descriptor_s *type_descriptor,
+	void **struct_ptr,	/* Pointer to a target structure's pointer */
+	const void *buffer,	/* Data to be decoded */
+	size_t size		/* Size of data buffer */
+	);
+
+/*
+ * Type of the type-specific XER decoder function.
+ */
+typedef asn_dec_rval_t (xer_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx,
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		void **struct_ptr,
+		const char *opt_mname,	/* Member name */
+		const void *buf_ptr, size_t size
+	);
+
+/*******************************
+ * INTERNALLY USEFUL FUNCTIONS *
+ *******************************/
+
+/*
+ * Generalized function for decoding the primitive values.
+ * Used by more specialized functions, such as OCTET_STRING_decode_xer_utf8
+ * and others. This function should not be used by applications, as its API
+ * is subject to changes.
+ */
+asn_dec_rval_t xer_decode_general(asn_codec_ctx_t *opt_codec_ctx,
+	asn_struct_ctx_t *ctx,	/* Type decoder context */
+	void *struct_key,	/* Treated as opaque pointer */
+	const char *xml_tag,	/* Expected XML tag name */
+	const void *buf_ptr, size_t size,
+	int (*opt_unexpected_tag_decoder)
+		(void *struct_key, const void *chunk_buf, size_t chunk_size),
+	ssize_t (*body_receiver)
+		(void *struct_key, const void *chunk_buf, size_t chunk_size,
+			int have_more)
+	);
+
+
+/*
+ * Fetch the next XER (XML) token from the stream.
+ * The function returns the number of bytes occupied by the chunk type,
+ * returned in the _ch_type. The _ch_type is only set (and valid) when
+ * the return value is >= 0.
+ */
+  typedef enum pxer_chunk_type {
+	PXER_WMORE,     /* Chunk type is not clear, more data expected. */
+	PXER_TAG,	    /* Complete XER tag */
+	PXER_TEXT,	    /* Plain text between XER tags */
+	PXER_COMMENT	/* A comment, may be part of */
+  } pxer_chunk_type_e;
+ssize_t xer_next_token(int *stateContext,
+	const void *buffer, size_t size, pxer_chunk_type_e *_ch_type);
+
+/*
+ * This function checks the buffer against the tag name is expected to occur.
+ */
+  typedef enum xer_check_tag {
+	XCT_BROKEN	= 0,	/* The tag is broken */
+	XCT_OPENING	= 1,	/* This is the <opening> tag */
+	XCT_CLOSING	= 2,	/* This is the </closing> tag */
+	XCT_BOTH	= 3,	/* This is the <modified/> tag */
+	XCT__UNK__MASK	= 4,	/* Mask of everything unexpected */
+	XCT_UNKNOWN_OP	= 5,	/* Unexpected <opening> tag */
+	XCT_UNKNOWN_CL	= 6,	/* Unexpected </closing> tag */
+	XCT_UNKNOWN_BO	= 7	/* Unexpected <modified/> tag */
+  } xer_check_tag_e;
+xer_check_tag_e xer_check_tag(const void *buf_ptr, int size,
+		const char *need_tag);
+
+/*
+ * Get the number of bytes consisting entirely of XER whitespace characters.
+ * RETURN VALUES:
+ * >=0:	Number of whitespace characters in the string.
+ */
+size_t xer_whitespace_span(const void *chunk_buf, size_t chunk_size);
+
+/*
+ * Skip the series of anticipated extensions.
+ */
+int xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _XER_DECODER_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/xer_encoder.c b/libkmod/pkcs7/asn1c-gen/xer_encoder.c
new file mode 100644
index 000000000000..4606575800d6
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/xer_encoder.c
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <stdio.h>
+#include <errno.h>
+
+/*
+ * The XER encoder of any type. May be invoked by the application.
+ */
+asn_enc_rval_t
+xer_encode(asn_TYPE_descriptor_t *td, void *sptr,
+	enum xer_encoder_flags_e xer_flags,
+		asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_enc_rval_t er, tmper;
+	const char *mname;
+	size_t mlen;
+	int xcan = (xer_flags & XER_F_CANONICAL) ? 1 : 2;
+
+	if(!td || !sptr) goto cb_failed;
+
+	mname = td->xml_tag;
+	mlen = strlen(mname);
+
+	ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
+
+	tmper = td->xer_encoder(td, sptr, 1, xer_flags, cb, app_key);
+	if(tmper.encoded == -1) return tmper;
+
+	ASN__CALLBACK3("</", 2, mname, mlen, ">\n", xcan);
+
+	er.encoded = 4 + xcan + (2 * mlen) + tmper.encoded;
+
+	ASN__ENCODED_OK(er);
+cb_failed:
+	ASN__ENCODE_FAILED;
+}
+
+/*
+ * This is a helper function for xer_fprint, which directs all incoming data
+ * into the provided file descriptor.
+ */
+static int
+xer__print2fp(const void *buffer, size_t size, void *app_key) {
+	FILE *stream = (FILE *)app_key;
+
+	if(fwrite(buffer, 1, size, stream) != size)
+		return -1;
+
+	return 0;
+}
+
+int
+xer_fprint(FILE *stream, asn_TYPE_descriptor_t *td, void *sptr) {
+	asn_enc_rval_t er;
+
+	if(!stream) stream = stdout;
+	if(!td || !sptr)
+		return -1;
+
+	er = xer_encode(td, sptr, XER_F_BASIC, xer__print2fp, stream);
+	if(er.encoded == -1)
+		return -1;
+
+	return fflush(stream);
+}
diff --git a/libkmod/pkcs7/asn1c-gen/xer_encoder.h b/libkmod/pkcs7/asn1c-gen/xer_encoder.h
new file mode 100644
index 000000000000..055e73c0c8b0
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/xer_encoder.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_XER_ENCODER_H_
+#define	_XER_ENCODER_H_
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;	/* Forward declaration */
+
+/* Flags used by the xer_encode() and (*xer_type_encoder_f), defined below */
+enum xer_encoder_flags_e {
+	/* Mode of encoding */
+	XER_F_BASIC	= 0x01,	/* BASIC-XER (pretty-printing) */
+	XER_F_CANONICAL	= 0x02	/* Canonical XER (strict rules) */
+};
+
+/*
+ * The XER encoder of any type. May be invoked by the application.
+ */
+asn_enc_rval_t xer_encode(struct asn_TYPE_descriptor_s *type_descriptor,
+		void *struct_ptr,	/* Structure to be encoded */
+		enum xer_encoder_flags_e xer_flags,
+		asn_app_consume_bytes_f *consume_bytes_cb,
+		void *app_key		/* Arbitrary callback argument */
+	);
+
+/*
+ * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC)
+ * output into the chosen file pointer.
+ * RETURN VALUES:
+ * 	 0: The structure is printed.
+ * 	-1: Problem printing the structure.
+ * WARNING: No sensible errno value is returned.
+ */
+int xer_fprint(FILE *stream, struct asn_TYPE_descriptor_s *td, void *sptr);
+
+/*
+ * Type of the generic XER encoder.
+ */
+typedef asn_enc_rval_t (xer_type_encoder_f)(
+		struct asn_TYPE_descriptor_s *type_descriptor,
+		void *struct_ptr,	/* Structure to be encoded */
+		int ilevel,		/* Level of indentation */
+		enum xer_encoder_flags_e xer_flags,
+		asn_app_consume_bytes_f *consume_bytes_cb,	/* Callback */
+		void *app_key		/* Arbitrary callback argument */
+	);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _XER_ENCODER_H_ */
diff --git a/libkmod/pkcs7/asn1c-gen/xer_support.c b/libkmod/pkcs7/asn1c-gen/xer_support.c
new file mode 100644
index 000000000000..36b4bfbfc07e
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/xer_support.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * 	All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_system.h>
+#include <xer_support.h>
+
+/* Parser states */
+typedef enum {
+	ST_TEXT,
+	ST_TAG_START,
+	ST_TAG_BODY,
+	ST_TAG_QUOTE_WAIT,
+	ST_TAG_QUOTED_STRING,
+	ST_TAG_UNQUOTED_STRING,
+	ST_COMMENT_WAIT_DASH1,	/* "<!--"[1] */
+	ST_COMMENT_WAIT_DASH2,	/* "<!--"[2] */
+	ST_COMMENT,
+	ST_COMMENT_CLO_DASH2,	/* "-->"[0] */
+	ST_COMMENT_CLO_RT	/* "-->"[1] */
+} pstate_e;
+
+static const int
+_charclass[256] = {
+	0,0,0,0,0,0,0,0, 0,1,1,0,1,1,0,0,
+	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+	1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+	2,2,2,2,2,2,2,2, 2,2,0,0,0,0,0,0,	/* 01234567 89       */
+	0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,	/*  ABCDEFG HIJKLMNO */
+	3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0,	/* PQRSTUVW XYZ      */
+	0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,	/*  abcdefg hijklmno */
+	3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0	/* pqrstuvw xyz      */
+};
+#define WHITESPACE(c)	(_charclass[(unsigned char)(c)] == 1)
+#define ALNUM(c)	(_charclass[(unsigned char)(c)] >= 2)
+#define ALPHA(c)	(_charclass[(unsigned char)(c)] == 3)
+
+/* Aliases for characters, ASCII/UTF-8 */
+#define	EXCLAM	0x21	/* '!' */
+#define	CQUOTE	0x22	/* '"' */
+#define	CDASH	0x2d	/* '-' */
+#define	CSLASH	0x2f	/* '/' */
+#define	LANGLE	0x3c	/* '<' */
+#define	CEQUAL	0x3d	/* '=' */
+#define	RANGLE	0x3e	/* '>' */
+#define	CQUEST	0x3f	/* '?' */
+
+/* Invoke token callback */
+#define	TOKEN_CB_CALL(type, _ns, _current_too, _final) do {	\
+		int _ret;					\
+		pstate_e ns  = _ns;				\
+		ssize_t _sz = (p - chunk_start) + _current_too;	\
+		if (!_sz) {					\
+			/* Shortcut */				\
+			state = _ns;				\
+			break;					\
+		}						\
+		_ret = cb(type, chunk_start, _sz, key);		\
+		if(_ret < _sz) {				\
+			if(_current_too && _ret == -1)		\
+				state = ns;			\
+			goto finish;				\
+		}						\
+		chunk_start = p + _current_too;			\
+		state = ns;					\
+	} while(0)
+
+#define TOKEN_CB(_type, _ns, _current_too)			\
+	TOKEN_CB_CALL(_type, _ns, _current_too, 0)
+
+#define PXML_TAG_FINAL_CHUNK_TYPE      PXML_TAG_END
+#define PXML_COMMENT_FINAL_CHUNK_TYPE  PXML_COMMENT_END
+
+#define TOKEN_CB_FINAL(_type, _ns, _current_too)		\
+	TOKEN_CB_CALL( _type ## _FINAL_CHUNK_TYPE , _ns, _current_too, 1)
+
+/*
+ * Parser itself
+ */
+ssize_t pxml_parse(int *stateContext, const void *xmlbuf, size_t size, pxml_callback_f *cb, void *key) {
+	pstate_e state = (pstate_e)*stateContext;
+	const char *chunk_start = (const char *)xmlbuf;
+	const char *p = chunk_start;
+	const char *end = p + size;
+
+	for(; p < end; p++) {
+	  int C = *(const unsigned char *)p;
+	  switch(state) {
+	  case ST_TEXT:
+		/*
+		 * Initial state: we're in the middle of some text,
+		 * or just have started.
+		 */
+		if (C == LANGLE) 
+			/* We're now in the tag, probably */
+			TOKEN_CB(PXML_TEXT, ST_TAG_START, 0);
+		break;
+	  case ST_TAG_START:
+		if (ALPHA(C) || (C == CSLASH))
+			state = ST_TAG_BODY;
+		else if (C == EXCLAM)
+			state = ST_COMMENT_WAIT_DASH1;
+		else 
+			/*
+			 * Not characters and not whitespace.
+			 * Must be something like "3 < 4".
+			 */
+			TOKEN_CB(PXML_TEXT, ST_TEXT, 1);/* Flush as data */
+		break;
+	  case ST_TAG_BODY:
+		switch(C) {
+		case RANGLE:
+			/* End of the tag */
+			TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1);
+			break;
+		case LANGLE:
+			/*
+			 * The previous tag wasn't completed, but still
+			 * recognized as valid. (Mozilla-compatible)
+			 */
+			TOKEN_CB_FINAL(PXML_TAG, ST_TAG_START, 0);	
+			break;
+		case CEQUAL:
+			state = ST_TAG_QUOTE_WAIT;
+			break;
+		}
+		break;
+	  case ST_TAG_QUOTE_WAIT:
+		/*
+		 * State after the equal sign ("=") in the tag.
+		 */
+		switch(C) {
+		case CQUOTE:
+			state = ST_TAG_QUOTED_STRING;
+			break;
+		case RANGLE:
+			/* End of the tag */
+			TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1);
+			break;
+		default:
+			if(!WHITESPACE(C))
+				/* Unquoted string value */
+				state = ST_TAG_UNQUOTED_STRING;
+		}
+		break;
+	  case ST_TAG_QUOTED_STRING:
+		/*
+		 * Tag attribute's string value in quotes.
+		 */
+		if(C == CQUOTE) {
+			/* Return back to the tag state */
+			state = ST_TAG_BODY;
+		}
+		break;
+	  case ST_TAG_UNQUOTED_STRING:
+		if(C == RANGLE) {
+			/* End of the tag */
+			TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1);
+		} else if(WHITESPACE(C)) {
+			/* Return back to the tag state */
+			state = ST_TAG_BODY;
+		}
+		break;
+	  case ST_COMMENT_WAIT_DASH1:
+		if(C == CDASH) {
+			state = ST_COMMENT_WAIT_DASH2;
+		} else {
+			/* Some ordinary tag. */
+			state = ST_TAG_BODY;
+		}
+		break;
+	  case ST_COMMENT_WAIT_DASH2:
+		if(C == CDASH) {
+			/* Seen "<--" */
+			state = ST_COMMENT;
+		} else {
+			/* Some ordinary tag */
+			state = ST_TAG_BODY;
+		}
+		break;
+	  case ST_COMMENT:
+		if(C == CDASH) {
+			state = ST_COMMENT_CLO_DASH2;
+		}
+		break;
+	  case ST_COMMENT_CLO_DASH2:
+		if(C == CDASH) {
+			state = ST_COMMENT_CLO_RT;
+		} else {
+			/* This is not an end of a comment */
+			state = ST_COMMENT;
+		}
+		break;
+	  case ST_COMMENT_CLO_RT:
+		if(C == RANGLE) {
+			TOKEN_CB_FINAL(PXML_COMMENT, ST_TEXT, 1);
+		} else if(C == CDASH) {
+			/* Maintain current state, still waiting for '>' */
+		} else {
+			state = ST_COMMENT;
+		}
+		break;
+	  } /* switch(*ptr) */
+	} /* for() */
+
+	/*
+	 * Flush the partially processed chunk, state permitting.
+	 */
+	if(p - chunk_start) {
+		switch (state) {
+		case ST_COMMENT:
+			TOKEN_CB(PXML_COMMENT, state, 0);
+			break;
+		case ST_TEXT:
+			TOKEN_CB(PXML_TEXT, state, 0);
+			break;
+		default: break;	/* a no-op */
+		}
+	}
+
+finish:
+	*stateContext = (int)state;
+	return chunk_start - (const char *)xmlbuf;
+}
+
diff --git a/libkmod/pkcs7/asn1c-gen/xer_support.h b/libkmod/pkcs7/asn1c-gen/xer_support.h
new file mode 100644
index 000000000000..8b01944ab584
--- /dev/null
+++ b/libkmod/pkcs7/asn1c-gen/xer_support.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef	_XER_SUPPORT_H_
+#define	_XER_SUPPORT_H_
+
+#include <asn_system.h>		/* Platform-specific types */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Types of data transferred to the application.
+ */
+typedef enum {
+	PXML_TEXT,	/* Plain text between XML tags. */
+	PXML_TAG,	/* A tag, starting with '<'. */
+	PXML_COMMENT,	/* An XML comment, including "<!--" and "-->". */
+	/* 
+	 * The following chunk types are reported if the chunk
+	 * terminates the specified XML element.
+	 */
+	PXML_TAG_END,		/* Tag ended */
+	PXML_COMMENT_END	/* Comment ended */
+} pxml_chunk_type_e;
+
+/*
+ * Callback function that is called by the parser when parsed data is
+ * available. The _opaque is the pointer to a field containing opaque user 
+ * data specified in pxml_create() call. The chunk type is _type and the text 
+ * data is the piece of buffer identified by _bufid (as supplied to
+ * pxml_feed() call) starting at offset _offset and of _size bytes size. 
+ * The chunk is NOT '\0'-terminated.
+ */
+typedef int (pxml_callback_f)(pxml_chunk_type_e _type,
+	const void *_chunk_data, size_t _chunk_size, void *_key);
+
+/*
+ * Parse the given buffer as it were a chunk of XML data.
+ * Invoke the specified callback each time the meaninful data is found.
+ * This function returns number of bytes consumed from the bufer.
+ * It will always be lesser than or equal to the specified _size.
+ * The next invocation of this function must account the difference.
+ */
+ssize_t pxml_parse(int *_stateContext, const void *_buf, size_t _size,
+	pxml_callback_f *cb, void *_key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _XER_SUPPORT_H_ */
-- 
2.16.2

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH] libkmod-signature: Fix crash when module signature is not present.
  2018-03-08 13:58 [PATCH RFC PKCS7 asn1c 1/2] libkmod-signature: implement pkcs7 parsing with asn1c compiler Yauheni Kaliuta
@ 2018-03-08 18:14 ` Michal Suchanek
  2018-03-12 20:41   ` Yauheni Kaliuta
  0 siblings, 1 reply; 13+ messages in thread
From: Michal Suchanek @ 2018-03-08 18:14 UTC (permalink / raw)
  To: Yauheni Kaliuta
  Cc: Michal Suchanek, Lucas De Marchi, linux-modules, Ferry van Steen,
	David Howells

The mod_sig is allocated on stack and when no signature is present it is not
initialized and contains garbage. Later when freeing mod_sig garbage pointer is
dereferenced.

Make mod_sig pointer initialized to NULL instead so it has meaningful value
only when a signature was stored in it. This somewhat straightens the interface
to kmod_module_signature_info as well.

Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
 libkmod/libkmod-internal.h  |  2 +-
 libkmod/libkmod-module.c    | 21 +++++++++---------
 libkmod/libkmod-signature.c | 53 +++++++++++++++++++++++++--------------------
 3 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/libkmod/libkmod-internal.h b/libkmod/libkmod-internal.h
index 2ad74c7a33a5..8bc9ecfb906e 100644
--- a/libkmod/libkmod-internal.h
+++ b/libkmod/libkmod-internal.h
@@ -192,5 +192,5 @@ struct kmod_signature_info {
 	void (*free)(void *);
 	void *private;
 };
-bool kmod_module_signature_info(const struct kmod_file *file, struct kmod_signature_info *sig_info) _must_check_ __attribute__((nonnull(1, 2)));
+struct kmod_signature_info *kmod_module_signature_info(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
 void kmod_module_signature_info_free(struct kmod_signature_info *sig_info) __attribute__((nonnull));
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
index 7b00d526edec..cbe35819932e 100644
--- a/libkmod/libkmod-module.c
+++ b/libkmod/libkmod-module.c
@@ -2304,7 +2304,7 @@ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_
 	struct kmod_elf *elf;
 	char **strings;
 	int i, count, ret = -ENOMEM;
-	struct kmod_signature_info sig_info;
+	struct kmod_signature_info *sig_info = NULL;
 
 	if (mod == NULL || list == NULL)
 		return -ENOENT;
@@ -2341,32 +2341,32 @@ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_
 			goto list_error;
 	}
 
-	if (kmod_module_signature_info(mod->file, &sig_info)) {
+	if (sig_info = kmod_module_signature_info(mod->file)) {
 		struct kmod_list *n;
 
 		n = kmod_module_info_append(list, "sig_id", strlen("sig_id"),
-				sig_info.id_type, strlen(sig_info.id_type));
+				sig_info->id_type, strlen(sig_info->id_type));
 		if (n == NULL)
 			goto list_error;
 		count++;
 
 		n = kmod_module_info_append(list, "signer", strlen("signer"),
-				sig_info.signer, sig_info.signer_len);
+				sig_info->signer, sig_info->signer_len);
 		if (n == NULL)
 			goto list_error;
 		count++;
 
 
 		n = kmod_module_info_append_hex(list, "sig_key", strlen("sig_key"),
-						sig_info.key_id,
-						sig_info.key_id_len);
+						sig_info->key_id,
+						sig_info->key_id_len);
 		if (n == NULL)
 			goto list_error;
 		count++;
 
 		n = kmod_module_info_append(list,
 				"sig_hashalgo", strlen("sig_hashalgo"),
-				sig_info.hash_algo, strlen(sig_info.hash_algo));
+				sig_info->hash_algo, strlen(sig_info->hash_algo));
 		if (n == NULL)
 			goto list_error;
 		count++;
@@ -2377,8 +2377,8 @@ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_
 		 */
 		n = kmod_module_info_append_hex(list, "signature",
 						strlen("signature"),
-						sig_info.sig,
-						sig_info.sig_len);
+						sig_info->sig,
+						sig_info->sig_len);
 
 		if (n == NULL)
 			goto list_error;
@@ -2389,7 +2389,8 @@ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_
 
 list_error:
 	/* aux structures freed in normal case also */
-	kmod_module_signature_info_free(&sig_info);
+	if (sig_info)
+		kmod_module_signature_info_free(sig_info);
 
 	if (ret < 0) {
 		kmod_module_info_free_list(*list);
diff --git a/libkmod/libkmod-signature.c b/libkmod/libkmod-signature.c
index bdf84cb14718..fae074e6dd1d 100644
--- a/libkmod/libkmod-signature.c
+++ b/libkmod/libkmod-signature.c
@@ -93,13 +93,17 @@ struct module_signature {
 	uint32_t sig_len;    /* Length of signature data (big endian) */
 };
 
-static bool
+static struct kmod_signature_info *
 kmod_module_signature_info_default(const char *mem,
 				   off_t size,
 				   const struct module_signature *modsig,
-				   size_t sig_len,
-				   struct kmod_signature_info *sig_info)
+				   size_t sig_len)
 {
+	struct kmod_signature_info *sig_info = malloc(sizeof *sig_info);
+
+	if (!sig_info)
+		return NULL;
+
 	size -= sig_len;
 	sig_info->sig = mem + size;
 	sig_info->sig_len = sig_len;
@@ -119,7 +123,7 @@ kmod_module_signature_info_default(const char *mem,
 	sig_info->free = NULL;
 	sig_info->private = NULL;
 
-	return true;
+	return sig_info;
 }
 
 static void kmod_module_signature_info_pkcs7_free(void *s)
@@ -129,13 +133,13 @@ static void kmod_module_signature_info_pkcs7_free(void *s)
 	pkcs7_free_cert(si->private);
 }
 
-static bool
+static struct kmod_signature_info *
 kmod_module_signature_info_pkcs7(const char *mem,
 				 off_t size,
 				 const struct module_signature *modsig,
-				 size_t sig_len,
-				 struct kmod_signature_info *sig_info)
+				 size_t sig_len)
 {
+	struct kmod_signature_info *sig_info = NULL;
 	const char *pkcs7_raw;
 	struct pkcs7_cert *cert;
 
@@ -144,7 +148,13 @@ kmod_module_signature_info_pkcs7(const char *mem,
 
 	cert = pkcs7_parse_cert(pkcs7_raw, sig_len);
 	if (cert == NULL)
-		return false;
+		return NULL;
+
+	sig_info = malloc(sizeof *sig_info);
+	if (!sig_info) {
+		free(cert);
+		return NULL;
+	}
 
 	sig_info->private = cert;
 	sig_info->free = kmod_module_signature_info_pkcs7_free;
@@ -162,7 +172,7 @@ kmod_module_signature_info_pkcs7(const char *mem,
 	sig_info->hash_algo = cert->hash_algo;
 	sig_info->id_type = pkey_id_type[modsig->id_type];
 
-	return true;
+	return sig_info;
 }
 
 #define SIG_MAGIC "~Module signature appended~\n"
@@ -178,48 +188,45 @@ kmod_module_signature_info_pkcs7(const char *mem,
  * [ SIG_MAGIC               ]
  */
 
-bool kmod_module_signature_info(const struct kmod_file *file, struct kmod_signature_info *sig_info)
+struct kmod_signature_info *kmod_module_signature_info(const struct kmod_file *file)
 {
 	const char *mem;
 	off_t size;
 	const struct module_signature *modsig;
 	size_t sig_len;
-	bool ret;
 
 	size = kmod_file_get_size(file);
 	mem = kmod_file_get_contents(file);
 	if (size < (off_t)strlen(SIG_MAGIC))
-		return false;
+		return NULL;
 	size -= strlen(SIG_MAGIC);
 	if (memcmp(SIG_MAGIC, mem + size, strlen(SIG_MAGIC)) != 0)
-		return false;
+		return NULL;
 
 	if (size < (off_t)sizeof(struct module_signature))
-		return false;
+		return NULL;
 	size -= sizeof(struct module_signature);
 	modsig = (struct module_signature *)(mem + size);
 	if (modsig->algo >= PKEY_ALGO__LAST ||
 			modsig->hash >= PKEY_HASH__LAST ||
 			modsig->id_type >= PKEY_ID_TYPE__LAST)
-		return false;
+		return NULL;
 	sig_len = be32toh(get_unaligned(&modsig->sig_len));
 	if (sig_len == 0 ||
 	    size < (int64_t)(modsig->signer_len + modsig->key_id_len + sig_len))
-		return false;
+		return NULL;
 
 	if (modsig->id_type == PKEY_ID_PKCS7)
-		ret = kmod_module_signature_info_pkcs7(mem, size,
-						       modsig, sig_len,
-						       sig_info);
+		return kmod_module_signature_info_pkcs7(mem, size,
+						        modsig, sig_len);
 	else
-		ret = kmod_module_signature_info_default(mem, size,
-							 modsig, sig_len,
-							 sig_info);
-	return ret;
+		return kmod_module_signature_info_default(mem, size,
+							  modsig, sig_len);
 }
 
 void kmod_module_signature_info_free(struct kmod_signature_info *sig_info)
 {
 	if (sig_info->free)
 		sig_info->free(sig_info);
+	free(sig_info);
 }
-- 
2.13.6

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH RFC PKCS7 asn1c 0/2] asn1c version of PKCS#7 parser
  2018-03-08 13:58 [PATCH RFC PKCS7 asn1c 0/2] asn1c version of PKCS#7 parser Yauheni Kaliuta
  2018-03-08 13:58 ` [PATCH RFC PKCS7 asn1c 2/2] libkmod, pkcs7: commit asn1c autogenerated files Yauheni Kaliuta
@ 2018-03-12 15:42 ` Michal Suchánek
  2018-03-12 20:40   ` Yauheni Kaliuta
  1 sibling, 1 reply; 13+ messages in thread
From: Michal Suchánek @ 2018-03-12 15:42 UTC (permalink / raw)
  To: Yauheni Kaliuta
  Cc: Lucas De Marchi, linux-modules, Ferry van Steen, David Howells

On Thu,  8 Mar 2018 15:58:08 +0200
Yauheni Kaliuta <yauheni.kaliuta@redhat.com> wrote:

> What bothers me is that asn1c files are generated under BSD
> license.

What bothers me more license-wise is the pkcs7.asn1 coming from kernel
which is licensed under GPL.

Thanks

Michal

> 
> Yauheni Kaliuta (2):
>   libkmod-signature: implement pkcs7 parsing with asn1c compiler
>   libkmod, pkcs7: commit asn1c autogenerated files
> 
>  Makefile.am                                        |   22 +-
>  configure.ac                                       |    1 +
>  libkmod/libkmod-internal.h                         |    3 +
>  libkmod/libkmod-module.c                           |    3 +
>  libkmod/libkmod-signature.c                        |  105 +-
>  libkmod/pkcs7/asn1c-gen/ANY.c                      |  158 ++
>  libkmod/pkcs7/asn1c-gen/ANY.h                      |   48 +
>  libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c  |   68 +
>  libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h  |   40 +
>  libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c   |   69 +
>  libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h   |   40 +
>  libkmod/pkcs7/asn1c-gen/BIT_STRING.c               |  189 ++
>  libkmod/pkcs7/asn1c-gen/BIT_STRING.h               |   33 +
>  libkmod/pkcs7/asn1c-gen/CRLSequence.c              |   52 +
>  libkmod/pkcs7/asn1c-gen/CRLSequence.h              |   44 +
>  libkmod/pkcs7/asn1c-gen/Certificate.c              |  104 ++
>  libkmod/pkcs7/asn1c-gen/Certificate.h              |   39 +
>  libkmod/pkcs7/asn1c-gen/CertificateList.c          |   52 +
>  libkmod/pkcs7/asn1c-gen/CertificateList.h          |   39 +
>  .../pkcs7/asn1c-gen/CertificateRevocationLists.c   |   52 +
>  .../pkcs7/asn1c-gen/CertificateRevocationLists.h   |   44 +
>  libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c  |  109 ++
>  libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h  |   39 +
>  libkmod/pkcs7/asn1c-gen/Certificates.c             |   52 +
>  libkmod/pkcs7/asn1c-gen/Certificates.h             |   39 +
>  libkmod/pkcs7/asn1c-gen/ContentInfo.c              |   69 +
>  libkmod/pkcs7/asn1c-gen/ContentInfo.h              |   40 +
>  libkmod/pkcs7/asn1c-gen/ContentType.c              |  109 ++
>  libkmod/pkcs7/asn1c-gen/ContentType.h              |   39 +
>  libkmod/pkcs7/asn1c-gen/Data.c                     |  104 ++
>  libkmod/pkcs7/asn1c-gen/Data.h                     |   39 +
>  .../pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c    |   68 +
>  .../pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h    |   40 +
>  .../pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c   |  153 ++
>  .../pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h   |   68 +
>  .../DigestEncryptionAlgorithmIdentifier.c          |   68 +
>  .../DigestEncryptionAlgorithmIdentifier.h          |   40 +
>  libkmod/pkcs7/asn1c-gen/EncryptedDigest.c          |  109 ++
>  libkmod/pkcs7/asn1c-gen/EncryptedDigest.h          |   39 +
>  .../ExtendedCertificatesAndCertificates.c          |   52 +
>  .../ExtendedCertificatesAndCertificates.h          |   39 +
>  libkmod/pkcs7/asn1c-gen/INTEGER.c                  | 1025 +++++++++++
>  libkmod/pkcs7/asn1c-gen/INTEGER.h                  |   82 +
>  libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c    |   65 +
>  libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h    |   39 +
>  libkmod/pkcs7/asn1c-gen/Makefile.am                |  131 ++
>  libkmod/pkcs7/asn1c-gen/Makefile.am.sample         |  150 ++
>  libkmod/pkcs7/asn1c-gen/Name.c                     |   52 +
>  libkmod/pkcs7/asn1c-gen/Name.h                     |   44 +
>  libkmod/pkcs7/asn1c-gen/NativeEnumerated.c         |  207 +++
>  libkmod/pkcs7/asn1c-gen/NativeEnumerated.h         |   32 +
>  libkmod/pkcs7/asn1c-gen/NativeInteger.c            |  332 ++++
>  libkmod/pkcs7/asn1c-gen/NativeInteger.h            |   37 +
>  libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c        |  764 +++++++++
>  libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h        |  139 ++
>  libkmod/pkcs7/asn1c-gen/OCTET_STRING.c             | 1807
> ++++++++++++++++++++
> libkmod/pkcs7/asn1c-gen/OCTET_STRING.h             |   86 +
> libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c         |   69 +
> libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h         |   45
> + .../pkcs7/asn1c-gen/RelativeDistinguishedName.c    |   52
> + .../pkcs7/asn1c-gen/RelativeDistinguishedName.h    |   44
> + .../pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c  |   52
> + .../pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h  |   44 +
> libkmod/pkcs7/asn1c-gen/SignedData.c               |  227 +++
> libkmod/pkcs7/asn1c-gen/SignedData.h               |   81 +
> libkmod/pkcs7/asn1c-gen/SignerIdentifier.c         |   65 +
> libkmod/pkcs7/asn1c-gen/SignerIdentifier.h         |   50 +
> libkmod/pkcs7/asn1c-gen/SignerInfo.c               |  371 ++++
> libkmod/pkcs7/asn1c-gen/SignerInfo.h               |  107 ++
> libkmod/pkcs7/asn1c-gen/SignerInfos.c              |  153 ++
> libkmod/pkcs7/asn1c-gen/SignerInfos.h              |   68 +
> libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c     |  109 ++
> libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h     |   39 +
> libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c |   69 +
> libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h |   40 +
> libkmod/pkcs7/asn1c-gen/Values.c                   |   52 +
> libkmod/pkcs7/asn1c-gen/Values.h                   |   39 +
> libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c          |   41 +
> libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h          |   52 +
> libkmod/pkcs7/asn1c-gen/asn_SET_OF.c               |   88 +
> libkmod/pkcs7/asn1c-gen/asn_SET_OF.h               |   62 +
> libkmod/pkcs7/asn1c-gen/asn_application.h          |   47 +
> libkmod/pkcs7/asn1c-gen/asn_codecs.h               |  109 ++
> libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c          |  312 ++++
> libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h          |   53 +
> libkmod/pkcs7/asn1c-gen/asn_internal.h             |  128 ++
> libkmod/pkcs7/asn1c-gen/asn_system.h               |  137 ++
> libkmod/pkcs7/asn1c-gen/ber_decoder.c              |  283 +++
> libkmod/pkcs7/asn1c-gen/ber_decoder.h              |   64 +
> libkmod/pkcs7/asn1c-gen/ber_tlv_length.c           |  178 ++
> libkmod/pkcs7/asn1c-gen/ber_tlv_length.h           |   50 +
> libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c              |  144 ++
> libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h              |   60 +
> libkmod/pkcs7/asn1c-gen/constr_CHOICE.c            | 1114
> ++++++++++++ libkmod/pkcs7/asn1c-gen/constr_CHOICE.h            |
> 57 + libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c          | 1425
> +++++++++++++++ libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h
> |   60 + libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c       |  208
> +++ libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h       |   33 +
> libkmod/pkcs7/asn1c-gen/constr_SET_OF.c            |  954 +++++++++++
> libkmod/pkcs7/asn1c-gen/constr_SET_OF.h            |   42 +
> libkmod/pkcs7/asn1c-gen/constr_TYPE.c              |   77 +
> libkmod/pkcs7/asn1c-gen/constr_TYPE.h              |  180 ++
> libkmod/pkcs7/asn1c-gen/constraints.c              |   93 +
> libkmod/pkcs7/asn1c-gen/constraints.h              |   63 +
> libkmod/pkcs7/asn1c-gen/converter-sample.c         |  834 +++++++++
> libkmod/pkcs7/asn1c-gen/der_encoder.c              |  201 +++
> libkmod/pkcs7/asn1c-gen/der_encoder.h              |   68 +
> libkmod/pkcs7/asn1c-gen/per_decoder.c              |   93 +
> libkmod/pkcs7/asn1c-gen/per_decoder.h              |   56 +
> libkmod/pkcs7/asn1c-gen/per_encoder.c              |  151 ++
> libkmod/pkcs7/asn1c-gen/per_encoder.h              |   69 +
> libkmod/pkcs7/asn1c-gen/per_opentype.c             |  378 ++++
> libkmod/pkcs7/asn1c-gen/per_opentype.h             |   22 +
> libkmod/pkcs7/asn1c-gen/per_support.c              |  483 ++++++
> libkmod/pkcs7/asn1c-gen/per_support.h              |  135 ++
> libkmod/pkcs7/asn1c-gen/xer_decoder.c              |  368 ++++
> libkmod/pkcs7/asn1c-gen/xer_decoder.h              |  106 ++
> libkmod/pkcs7/asn1c-gen/xer_encoder.c              |   67 +
> libkmod/pkcs7/asn1c-gen/xer_encoder.h              |   59 +
> libkmod/pkcs7/asn1c-gen/xer_support.c              |  227 +++
> libkmod/pkcs7/asn1c-gen/xer_support.h              |   55 +
> libkmod/pkcs7/pkcs7.asn1                           |  135 ++
> libkmod/pkcs7/pkcs7_parser.c                       |  297 ++++
> libkmod/pkcs7/pkcs7_parser.h                       |   42 + 125 files
> changed, 19228 insertions(+), 20 deletions(-) create mode 100644
> libkmod/pkcs7/asn1c-gen/ANY.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ANY.h create mode 100644
> libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c create mode 100644
> libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h create mode 100644
> libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c create mode 100644
> libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h create mode 100644
> libkmod/pkcs7/asn1c-gen/BIT_STRING.c create mode 100644
> libkmod/pkcs7/asn1c-gen/BIT_STRING.h create mode 100644
> libkmod/pkcs7/asn1c-gen/CRLSequence.c create mode 100644
> libkmod/pkcs7/asn1c-gen/CRLSequence.h create mode 100644
> libkmod/pkcs7/asn1c-gen/Certificate.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Certificate.h create mode 100644
> libkmod/pkcs7/asn1c-gen/CertificateList.c create mode 100644
> libkmod/pkcs7/asn1c-gen/CertificateList.h create mode 100644
> libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c create mode
> 100644 libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c create
> mode 100644 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/Certificates.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Certificates.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ContentInfo.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ContentInfo.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ContentType.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ContentType.h create mode 100644
> libkmod/pkcs7/asn1c-gen/Data.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Data.h create mode 100644
> libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c create mode
> 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c
> create mode 100644
> libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h create mode
> 100644 libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c
> create mode 100644
> libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/EncryptedDigest.c create mode
> 100644 libkmod/pkcs7/asn1c-gen/EncryptedDigest.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c create
> mode 100644
> libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/INTEGER.c create mode 100644
> libkmod/pkcs7/asn1c-gen/INTEGER.h create mode 100644
> libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c create mode 100644
> libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h create mode 100644
> libkmod/pkcs7/asn1c-gen/Makefile.am create mode 100644
> libkmod/pkcs7/asn1c-gen/Makefile.am.sample create mode 100644
> libkmod/pkcs7/asn1c-gen/Name.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Name.h create mode 100644
> libkmod/pkcs7/asn1c-gen/NativeEnumerated.c create mode 100644
> libkmod/pkcs7/asn1c-gen/NativeEnumerated.h create mode 100644
> libkmod/pkcs7/asn1c-gen/NativeInteger.c create mode 100644
> libkmod/pkcs7/asn1c-gen/NativeInteger.h create mode 100644
> libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c create mode 100644
> libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h create mode 100644
> libkmod/pkcs7/asn1c-gen/OCTET_STRING.c create mode 100644
> libkmod/pkcs7/asn1c-gen/OCTET_STRING.h create mode 100644
> libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c create mode 100644
> libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h create mode 100644
> libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c create mode
> 100644 libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c
> create mode 100644
> libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h create mode
> 100644 libkmod/pkcs7/asn1c-gen/SignedData.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SignedData.h create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerIdentifier.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerIdentifier.h create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerInfo.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerInfo.h create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerInfos.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerInfos.h create mode 100644
> libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h create mode 100644
> libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c create mode 100644
> libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h create mode 100644
> libkmod/pkcs7/asn1c-gen/Values.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Values.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_SET_OF.c create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_SET_OF.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_application.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_codecs.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_internal.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_system.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_decoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_decoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_tlv_length.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_tlv_length.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_CHOICE.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_CHOICE.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SET_OF.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SET_OF.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_TYPE.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_TYPE.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constraints.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constraints.h create mode 100644
> libkmod/pkcs7/asn1c-gen/converter-sample.c create mode 100644
> libkmod/pkcs7/asn1c-gen/der_encoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/der_encoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/per_decoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/per_decoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/per_encoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/per_encoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/per_opentype.c create mode 100644
> libkmod/pkcs7/asn1c-gen/per_opentype.h create mode 100644
> libkmod/pkcs7/asn1c-gen/per_support.c create mode 100644
> libkmod/pkcs7/asn1c-gen/per_support.h create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_decoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_decoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_encoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_encoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_support.c create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_support.h create mode 100644
> libkmod/pkcs7/pkcs7.asn1 create mode 100644
> libkmod/pkcs7/pkcs7_parsepr.c create mode 100644
> libkmod/pkcs7/pkcs7_parser.h
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH RFC PKCS7 asn1c 2/2] libkmod, pkcs7: commit asn1c autogenerated files
  2018-03-08 13:58 ` [PATCH RFC PKCS7 asn1c 2/2] libkmod, pkcs7: commit asn1c autogenerated files Yauheni Kaliuta
@ 2018-03-12 15:45   ` Michal Suchánek
  0 siblings, 0 replies; 13+ messages in thread
From: Michal Suchánek @ 2018-03-12 15:45 UTC (permalink / raw)
  To: Yauheni Kaliuta
  Cc: Lucas De Marchi, linux-modules, Ferry van Steen, David Howells

Hello,

I think it would make more sense to *not* include the generated files
in git.

Similarly configure script is not included in git but is generated for
release tarballs.

Thanks

Michal

On Thu,  8 Mar 2018 15:58:10 +0200
Yauheni Kaliuta <yauheni.kaliuta@redhat.com> wrote:

> Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
> ---
>  libkmod/pkcs7/asn1c-gen/ANY.c                      |  158 ++
>  libkmod/pkcs7/asn1c-gen/ANY.h                      |   48 +
>  libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c  |   68 +
>  libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h  |   40 +
>  libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c   |   69 +
>  libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h   |   40 +
>  libkmod/pkcs7/asn1c-gen/BIT_STRING.c               |  189 ++
>  libkmod/pkcs7/asn1c-gen/BIT_STRING.h               |   33 +
>  libkmod/pkcs7/asn1c-gen/CRLSequence.c              |   52 +
>  libkmod/pkcs7/asn1c-gen/CRLSequence.h              |   44 +
>  libkmod/pkcs7/asn1c-gen/Certificate.c              |  104 ++
>  libkmod/pkcs7/asn1c-gen/Certificate.h              |   39 +
>  libkmod/pkcs7/asn1c-gen/CertificateList.c          |   52 +
>  libkmod/pkcs7/asn1c-gen/CertificateList.h          |   39 +
>  .../pkcs7/asn1c-gen/CertificateRevocationLists.c   |   52 +
>  .../pkcs7/asn1c-gen/CertificateRevocationLists.h   |   44 +
>  libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c  |  109 ++
>  libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h  |   39 +
>  libkmod/pkcs7/asn1c-gen/Certificates.c             |   52 +
>  libkmod/pkcs7/asn1c-gen/Certificates.h             |   39 +
>  libkmod/pkcs7/asn1c-gen/ContentInfo.c              |   69 +
>  libkmod/pkcs7/asn1c-gen/ContentInfo.h              |   40 +
>  libkmod/pkcs7/asn1c-gen/ContentType.c              |  109 ++
>  libkmod/pkcs7/asn1c-gen/ContentType.h              |   39 +
>  libkmod/pkcs7/asn1c-gen/Data.c                     |  104 ++
>  libkmod/pkcs7/asn1c-gen/Data.h                     |   39 +
>  .../pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c    |   68 +
>  .../pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h    |   40 +
>  .../pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c   |  153 ++
>  .../pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h   |   68 +
>  .../DigestEncryptionAlgorithmIdentifier.c          |   68 +
>  .../DigestEncryptionAlgorithmIdentifier.h          |   40 +
>  libkmod/pkcs7/asn1c-gen/EncryptedDigest.c          |  109 ++
>  libkmod/pkcs7/asn1c-gen/EncryptedDigest.h          |   39 +
>  .../ExtendedCertificatesAndCertificates.c          |   52 +
>  .../ExtendedCertificatesAndCertificates.h          |   39 +
>  libkmod/pkcs7/asn1c-gen/INTEGER.c                  | 1025 +++++++++++
>  libkmod/pkcs7/asn1c-gen/INTEGER.h                  |   82 +
>  libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c    |   65 +
>  libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h    |   39 +
>  libkmod/pkcs7/asn1c-gen/Makefile.am.sample         |  150 ++
>  libkmod/pkcs7/asn1c-gen/Name.c                     |   52 +
>  libkmod/pkcs7/asn1c-gen/Name.h                     |   44 +
>  libkmod/pkcs7/asn1c-gen/NativeEnumerated.c         |  207 +++
>  libkmod/pkcs7/asn1c-gen/NativeEnumerated.h         |   32 +
>  libkmod/pkcs7/asn1c-gen/NativeInteger.c            |  332 ++++
>  libkmod/pkcs7/asn1c-gen/NativeInteger.h            |   37 +
>  libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c        |  764 +++++++++
>  libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h        |  139 ++
>  libkmod/pkcs7/asn1c-gen/OCTET_STRING.c             | 1807
> ++++++++++++++++++++
> libkmod/pkcs7/asn1c-gen/OCTET_STRING.h             |   86 +
> libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c         |   69 +
> libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h         |   45
> + .../pkcs7/asn1c-gen/RelativeDistinguishedName.c    |   52
> + .../pkcs7/asn1c-gen/RelativeDistinguishedName.h    |   44
> + .../pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c  |   52
> + .../pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h  |   44 +
> libkmod/pkcs7/asn1c-gen/SignedData.c               |  227 +++
> libkmod/pkcs7/asn1c-gen/SignedData.h               |   81 +
> libkmod/pkcs7/asn1c-gen/SignerIdentifier.c         |   65 +
> libkmod/pkcs7/asn1c-gen/SignerIdentifier.h         |   50 +
> libkmod/pkcs7/asn1c-gen/SignerInfo.c               |  371 ++++
> libkmod/pkcs7/asn1c-gen/SignerInfo.h               |  107 ++
> libkmod/pkcs7/asn1c-gen/SignerInfos.c              |  153 ++
> libkmod/pkcs7/asn1c-gen/SignerInfos.h              |   68 +
> libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c     |  109 ++
> libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h     |   39 +
> libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c |   69 +
> libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h |   40 +
> libkmod/pkcs7/asn1c-gen/Values.c                   |   52 +
> libkmod/pkcs7/asn1c-gen/Values.h                   |   39 +
> libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c          |   41 +
> libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h          |   52 +
> libkmod/pkcs7/asn1c-gen/asn_SET_OF.c               |   88 +
> libkmod/pkcs7/asn1c-gen/asn_SET_OF.h               |   62 +
> libkmod/pkcs7/asn1c-gen/asn_application.h          |   47 +
> libkmod/pkcs7/asn1c-gen/asn_codecs.h               |  109 ++
> libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c          |  312 ++++
> libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h          |   53 +
> libkmod/pkcs7/asn1c-gen/asn_internal.h             |  128 ++
> libkmod/pkcs7/asn1c-gen/asn_system.h               |  137 ++
> libkmod/pkcs7/asn1c-gen/ber_decoder.c              |  283 +++
> libkmod/pkcs7/asn1c-gen/ber_decoder.h              |   64 +
> libkmod/pkcs7/asn1c-gen/ber_tlv_length.c           |  178 ++
> libkmod/pkcs7/asn1c-gen/ber_tlv_length.h           |   50 +
> libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c              |  144 ++
> libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h              |   60 +
> libkmod/pkcs7/asn1c-gen/constr_CHOICE.c            | 1114
> ++++++++++++ libkmod/pkcs7/asn1c-gen/constr_CHOICE.h            |
> 57 + libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c          | 1425
> +++++++++++++++ libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h
> |   60 + libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c       |  208
> +++ libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h       |   33 +
> libkmod/pkcs7/asn1c-gen/constr_SET_OF.c            |  954 +++++++++++
> libkmod/pkcs7/asn1c-gen/constr_SET_OF.h            |   42 +
> libkmod/pkcs7/asn1c-gen/constr_TYPE.c              |   77 +
> libkmod/pkcs7/asn1c-gen/constr_TYPE.h              |  180 ++
> libkmod/pkcs7/asn1c-gen/constraints.c              |   93 +
> libkmod/pkcs7/asn1c-gen/constraints.h              |   63 +
> libkmod/pkcs7/asn1c-gen/converter-sample.c         |  834 +++++++++
> libkmod/pkcs7/asn1c-gen/der_encoder.c              |  201 +++
> libkmod/pkcs7/asn1c-gen/der_encoder.h              |   68 +
> libkmod/pkcs7/asn1c-gen/per_decoder.c              |   93 +
> libkmod/pkcs7/asn1c-gen/per_decoder.h              |   56 +
> libkmod/pkcs7/asn1c-gen/per_encoder.c              |  151 ++
> libkmod/pkcs7/asn1c-gen/per_encoder.h              |   69 +
> libkmod/pkcs7/asn1c-gen/per_opentype.c             |  378 ++++
> libkmod/pkcs7/asn1c-gen/per_opentype.h             |   22 +
> libkmod/pkcs7/asn1c-gen/per_support.c              |  483 ++++++
> libkmod/pkcs7/asn1c-gen/per_support.h              |  135 ++
> libkmod/pkcs7/asn1c-gen/xer_decoder.c              |  368 ++++
> libkmod/pkcs7/asn1c-gen/xer_decoder.h              |  106 ++
> libkmod/pkcs7/asn1c-gen/xer_encoder.c              |   67 +
> libkmod/pkcs7/asn1c-gen/xer_encoder.h              |   59 +
> libkmod/pkcs7/asn1c-gen/xer_support.c              |  227 +++
> libkmod/pkcs7/asn1c-gen/xer_support.h              |   55 + 116 files
> changed, 18509 insertions(+) create mode 100644
> libkmod/pkcs7/asn1c-gen/ANY.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ANY.h create mode 100644
> libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c create mode 100644
> libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h create mode 100644
> libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c create mode 100644
> libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h create mode 100644
> libkmod/pkcs7/asn1c-gen/BIT_STRING.c create mode 100644
> libkmod/pkcs7/asn1c-gen/BIT_STRING.h create mode 100644
> libkmod/pkcs7/asn1c-gen/CRLSequence.c create mode 100644
> libkmod/pkcs7/asn1c-gen/CRLSequence.h create mode 100644
> libkmod/pkcs7/asn1c-gen/Certificate.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Certificate.h create mode 100644
> libkmod/pkcs7/asn1c-gen/CertificateList.c create mode 100644
> libkmod/pkcs7/asn1c-gen/CertificateList.h create mode 100644
> libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c create mode
> 100644 libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c create
> mode 100644 libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/Certificates.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Certificates.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ContentInfo.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ContentInfo.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ContentType.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ContentType.h create mode 100644
> libkmod/pkcs7/asn1c-gen/Data.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Data.h create mode 100644
> libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c create mode
> 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c
> create mode 100644
> libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h create mode
> 100644 libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c
> create mode 100644
> libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/EncryptedDigest.c create mode
> 100644 libkmod/pkcs7/asn1c-gen/EncryptedDigest.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c create
> mode 100644
> libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/INTEGER.c create mode 100644
> libkmod/pkcs7/asn1c-gen/INTEGER.h create mode 100644
> libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c create mode 100644
> libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h create mode 100644
> libkmod/pkcs7/asn1c-gen/Makefile.am.sample create mode 100644
> libkmod/pkcs7/asn1c-gen/Name.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Name.h create mode 100644
> libkmod/pkcs7/asn1c-gen/NativeEnumerated.c create mode 100644
> libkmod/pkcs7/asn1c-gen/NativeEnumerated.h create mode 100644
> libkmod/pkcs7/asn1c-gen/NativeInteger.c create mode 100644
> libkmod/pkcs7/asn1c-gen/NativeInteger.h create mode 100644
> libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c create mode 100644
> libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h create mode 100644
> libkmod/pkcs7/asn1c-gen/OCTET_STRING.c create mode 100644
> libkmod/pkcs7/asn1c-gen/OCTET_STRING.h create mode 100644
> libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c create mode 100644
> libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h create mode 100644
> libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c create mode
> 100644 libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h create
> mode 100644 libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c
> create mode 100644
> libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h create mode
> 100644 libkmod/pkcs7/asn1c-gen/SignedData.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SignedData.h create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerIdentifier.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerIdentifier.h create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerInfo.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerInfo.h create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerInfos.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SignerInfos.h create mode 100644
> libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c create mode 100644
> libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h create mode 100644
> libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c create mode 100644
> libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h create mode 100644
> libkmod/pkcs7/asn1c-gen/Values.c create mode 100644
> libkmod/pkcs7/asn1c-gen/Values.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_SET_OF.c create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_SET_OF.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_application.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_codecs.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_internal.h create mode 100644
> libkmod/pkcs7/asn1c-gen/asn_system.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_decoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_decoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_tlv_length.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_tlv_length.h create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c create mode 100644
> libkmod/pkcs7/asn1c-gen/ber_tlv_tag.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_CHOICE.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_CHOICE.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SEQUENCE.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SEQUENCE_OF.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SET_OF.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_SET_OF.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_TYPE.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constr_TYPE.h create mode 100644
> libkmod/pkcs7/asn1c-gen/constraints.c create mode 100644
> libkmod/pkcs7/asn1c-gen/constraints.h create mode 100644
> libkmod/pkcs7/asn1c-gen/converter-sample.c create mode 100644
> libkmod/pkcs7/asn1c-gen/der_encoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/der_encoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/per_decoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/per_decoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/per_encoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/per_encoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/per_opentype.c create mode 100644
> libkmod/pkcs7/asn1c-gen/per_opentype.h create mode 100644
> libkmod/pkcs7/asn1c-gen/per_support.c create mode 100644
> libkmod/pkcs7/asn1c-gen/per_support.h create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_decoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_decoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_encoder.c create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_encoder.h create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_support.c create mode 100644
> libkmod/pkcs7/asn1c-gen/xer_support.h
>=20
> diff --git a/libkmod/pkcs7/asn1c-gen/ANY.c
> b/libkmod/pkcs7/asn1c-gen/ANY.c new file mode 100644
> index 000000000000..77024bdcf3c9
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ANY.c
> @@ -0,0 +1,158 @@
> +/*-
> + * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <ANY.h>
> +#include <errno.h>
> +
> +static asn_OCTET_STRING_specifics_t asn_DEF_ANY_specs =3D {
> +	sizeof(ANY_t),
> +	offsetof(ANY_t, _asn_ctx),
> +	ASN_OSUBV_ANY
> +};
> +asn_TYPE_descriptor_t asn_DEF_ANY =3D {
> +	"ANY",
> +	"ANY",
> +	OCTET_STRING_free,
> +	OCTET_STRING_print,
> +	asn_generic_no_constraint,
> +	OCTET_STRING_decode_ber,
> +	OCTET_STRING_encode_der,
> +	OCTET_STRING_decode_xer_hex,
> +	ANY_encode_xer,
> +	0, 0,
> +	0, /* Use generic outmost tag fetcher */
> +	0, 0, 0, 0,
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	&asn_DEF_ANY_specs,
> +};
> +
> +
> +asn_enc_rval_t
> +ANY_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
> +	int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +
> +	if(flags & XER_F_CANONICAL) {
> +		/*
> +		 * Canonical XER-encoding of ANY type is not
> supported.
> +		 */
> +		ASN__ENCODE_FAILED;
> +	}
> +
> +	/* Dump as binary */
> +	return OCTET_STRING_encode_xer(td, sptr, ilevel, flags, cb,
> app_key); +}
> +
> +struct _callback_arg {
> +	uint8_t *buffer;
> +	size_t offset;
> +	size_t size;
> +};
> +
> +static int ANY__consume_bytes(const void *buffer, size_t size, void
> *key); +
> +int
> +ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
> +	struct _callback_arg arg;
> +	asn_enc_rval_t erval;
> +
> +	if(!st || !td) {
> +		errno =3D EINVAL;
> +		return -1;
> +	}
> +
> +	if(!sptr) {
> +		if(st->buf) FREEMEM(st->buf);
> +		st->size =3D 0;
> +		return 0;
> +	}
> +
> +	arg.offset =3D arg.size =3D 0;
> +	arg.buffer =3D 0;
> +
> +	erval =3D der_encode(td, sptr, ANY__consume_bytes, &arg);
> +	if(erval.encoded =3D=3D -1) {
> +		if(arg.buffer) FREEMEM(arg.buffer);
> +		return -1;
> +	}
> +	assert((size_t)erval.encoded =3D=3D arg.offset);
> +
> +	if(st->buf) FREEMEM(st->buf);
> +	st->buf =3D arg.buffer;
> +	st->size =3D arg.offset;
> +
> +	return 0;
> +}
> +
> +ANY_t *
> +ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
> +	ANY_t tmp;
> +	ANY_t *st;
> +
> +	if(!td || !sptr) {
> +		errno =3D EINVAL;
> +		return 0;
> +	}
> +
> +	memset(&tmp, 0, sizeof(tmp));
> +
> +	if(ANY_fromType(&tmp, td, sptr)) return 0;
> +
> +	st =3D (ANY_t *)CALLOC(1, sizeof(ANY_t));
> +	if(st) {
> +		*st =3D tmp;
> +		return st;
> +	} else {
> +		FREEMEM(tmp.buf);
> +		return 0;
> +	}
> +}
> +
> +int
> +ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr)
> {
> +	asn_dec_rval_t rval;
> +	void *newst =3D 0;
> +
> +	if(!st || !td || !struct_ptr) {
> +		errno =3D EINVAL;
> +		return -1;
> +	}
> +
> +	if(st->buf =3D=3D 0) {
> +		/* Nothing to convert, make it empty. */
> +		*struct_ptr =3D (void *)0;
> +		return 0;
> +	}
> +
> +	rval =3D ber_decode(0, td, (void **)&newst, st->buf, st->size);
> +	if(rval.code =3D=3D RC_OK) {
> +		*struct_ptr =3D newst;
> +		return 0;
> +	} else {
> +		/* Remove possibly partially decoded data. */
> +		ASN_STRUCT_FREE(*td, newst);
> +		return -1;
> +	}
> +}
> +
> +static int ANY__consume_bytes(const void *buffer, size_t size, void
> *key) {
> +	struct _callback_arg *arg =3D (struct _callback_arg *)key;
> +
> +	if((arg->offset + size) >=3D arg->size) {
> +		size_t nsize =3D (arg->size ? arg->size << 2 : 16) +
> size;
> +		void *p =3D REALLOC(arg->buffer, nsize);
> +		if(!p) return -1;
> +		arg->buffer =3D (uint8_t *)p;
> +		arg->size =3D nsize;
> +	}
> +
> +	memcpy(arg->buffer + arg->offset, buffer, size);
> +	arg->offset +=3D size;
> +	assert(arg->offset < arg->size);
> +
> +	return 0;
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/ANY.h
> b/libkmod/pkcs7/asn1c-gen/ANY.h new file mode 100644
> index 000000000000..b7d92fa98265
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ANY.h
> @@ -0,0 +1,48 @@
> +/*-
> + * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef ASN_TYPE_ANY_H
> +#define ASN_TYPE_ANY_H
> +
> +#include <OCTET_STRING.h>	/* Implemented via OCTET STRING
> type */ +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef struct ANY {
> +	uint8_t *buf;	/* BER-encoded ANY contents */
> +	int size;	/* Size of the above buffer */
> +
> +	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer
> boundaries */ +} ANY_t;
> +
> +extern asn_TYPE_descriptor_t asn_DEF_ANY;
> +
> +asn_struct_free_f ANY_free;
> +asn_struct_print_f ANY_print;
> +ber_type_decoder_f ANY_decode_ber;
> +der_type_encoder_f ANY_encode_der;
> +xer_type_encoder_f ANY_encode_xer;
> +
> +/******************************
> + * Handy conversion routines. *
> + ******************************/
> +
> +/* Convert another ASN.1 type into the ANY. This implies DER
> encoding. */ +int ANY_fromType(ANY_t *, asn_TYPE_descriptor_t *td,
> void *struct_ptr); +ANY_t *ANY_new_fromType(asn_TYPE_descriptor_t
> *td, void *struct_ptr); +
> +/* Convert the contents of the ANY type into the specified type. */
> +int ANY_to_type(ANY_t *, asn_TYPE_descriptor_t *td, void
> **struct_ptr); +
> +#define	ANY_fromBuf(s, buf, size)
> OCTET_STRING_fromBuf((s), (buf), (size)) +#define
> ANY_new_fromBuf(buf, size)	OCTET_STRING_new_fromBuf(	\
> +						&asn_DEF_ANY, (buf),
> (size)) +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* ASN_TYPE_ANY_H */
> diff --git a/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c
> b/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c new file mode
> 100644 index 000000000000..ec2db00c6ce0
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.c
> @@ -0,0 +1,68 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "AttributeValueAssertion.h"
> +
> +static asn_TYPE_member_t asn_MBR_AttributeValueAssertion_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct AttributeValueAssertion,
> attributeType),
> +		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
> +		0,
> +		&asn_DEF_OBJECT_IDENTIFIER,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"attributeType"
> +		},
> +	{ ATF_OPEN_TYPE | ATF_NOFLAGS, 0, offsetof(struct
> AttributeValueAssertion, attributeValue),
> +		-1 /* Ambiguous tag (ANY?) */,
> +		0,
> +		&asn_DEF_ANY,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"attributeValue"
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_AttributeValueAssertion_tags_1[]
> =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_AttributeValueAssertion_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 } /*
> attributeType */ +};
> +static asn_SEQUENCE_specifics_t
> asn_SPC_AttributeValueAssertion_specs_1 =3D {
> +	sizeof(struct AttributeValueAssertion),
> +	offsetof(struct AttributeValueAssertion, _asn_ctx),
> +	asn_MAP_AttributeValueAssertion_tag2el_1,
> +	1,	/* Count of tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_AttributeValueAssertion =3D {
> +	"AttributeValueAssertion",
> +	"AttributeValueAssertion",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_AttributeValueAssertion_tags_1,
> +	sizeof(asn_DEF_AttributeValueAssertion_tags_1)
> +		/sizeof(asn_DEF_AttributeValueAssertion_tags_1[0]), /*
> 1 */
> +	asn_DEF_AttributeValueAssertion_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_AttributeValueAssertion_tags_1)
> +		/sizeof(asn_DEF_AttributeValueAssertion_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_AttributeValueAssertion_1,
> +	2,	/* Elements count */
> +	&asn_SPC_AttributeValueAssertion_specs_1	/*
> Additional specs */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h
> b/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h new file mode
> 100644 index 000000000000..3446d61e89dc
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/AttributeValueAssertion.h
> @@ -0,0 +1,40 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_AttributeValueAssertion_H_
> +#define	_AttributeValueAssertion_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <OBJECT_IDENTIFIER.h>
> +#include <ANY.h>
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* AttributeValueAssertion */
> +typedef struct AttributeValueAssertion {
> +	OBJECT_IDENTIFIER_t	 attributeType;
> +	ANY_t	 attributeValue;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} AttributeValueAssertion_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_AttributeValueAssertion;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _AttributeValueAssertion_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c
> b/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c new file mode
> 100644 index 000000000000..011505b60e05
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.c
> @@ -0,0 +1,69 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "AuthenticatedAttribute.h"
> +
> +static asn_TYPE_member_t asn_MBR_AuthenticatedAttribute_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct AuthenticatedAttribute,
> type),
> +		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
> +		0,
> +		&asn_DEF_OBJECT_IDENTIFIER,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"type"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct AuthenticatedAttribute,
> values),
> +		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
> +		0,
> +		&asn_DEF_Values,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"values"
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_AuthenticatedAttribute_tags_1[] =3D
> {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_AuthenticatedAttribute_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /* type */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 1, 0, 0 } /* values */
> +};
> +static asn_SEQUENCE_specifics_t
> asn_SPC_AuthenticatedAttribute_specs_1 =3D {
> +	sizeof(struct AuthenticatedAttribute),
> +	offsetof(struct AuthenticatedAttribute, _asn_ctx),
> +	asn_MAP_AuthenticatedAttribute_tag2el_1,
> +	2,	/* Count of tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_AuthenticatedAttribute =3D {
> +	"AuthenticatedAttribute",
> +	"AuthenticatedAttribute",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_AuthenticatedAttribute_tags_1,
> +	sizeof(asn_DEF_AuthenticatedAttribute_tags_1)
> +		/sizeof(asn_DEF_AuthenticatedAttribute_tags_1[0]), /*
> 1 */
> +	asn_DEF_AuthenticatedAttribute_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_AuthenticatedAttribute_tags_1)
> +		/sizeof(asn_DEF_AuthenticatedAttribute_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_AuthenticatedAttribute_1,
> +	2,	/* Elements count */
> +	&asn_SPC_AuthenticatedAttribute_specs_1	/* Additional
> specs */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h
> b/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h new file mode
> 100644 index 000000000000..a140afb7f31a
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/AuthenticatedAttribute.h
> @@ -0,0 +1,40 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_AuthenticatedAttribute_H_
> +#define	_AuthenticatedAttribute_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <OBJECT_IDENTIFIER.h>
> +#include "Values.h"
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* AuthenticatedAttribute */
> +typedef struct AuthenticatedAttribute {
> +	OBJECT_IDENTIFIER_t	 type;
> +	Values_t	 values;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} AuthenticatedAttribute_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_AuthenticatedAttribute;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _AuthenticatedAttribute_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/BIT_STRING.c
> b/libkmod/pkcs7/asn1c-gen/BIT_STRING.c new file mode 100644
> index 000000000000..997ff41619e3
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/BIT_STRING.c
> @@ -0,0 +1,189 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <BIT_STRING.h>
> +#include <asn_internal.h>
> +
> +/*
> + * BIT STRING basic type description.
> + */
> +static const ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
> +};
> +static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs =3D {
> +	sizeof(BIT_STRING_t),
> +	offsetof(BIT_STRING_t, _asn_ctx),
> +	ASN_OSUBV_BIT
> +};
> +asn_TYPE_descriptor_t asn_DEF_BIT_STRING =3D {
> +	"BIT STRING",
> +	"BIT_STRING",
> +	OCTET_STRING_free,         /* Implemented in terms of OCTET
> STRING */
> +	BIT_STRING_print,
> +	BIT_STRING_constraint,
> +	OCTET_STRING_decode_ber,   /* Implemented in terms of OCTET
> STRING */
> +	OCTET_STRING_encode_der,   /* Implemented in terms of OCTET
> STRING */
> +	OCTET_STRING_decode_xer_binary,
> +	BIT_STRING_encode_xer,
> +	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
> +	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
> +	0, /* Use generic outmost tag fetcher */
> +	asn_DEF_BIT_STRING_tags,
> +	sizeof(asn_DEF_BIT_STRING_tags)
> +	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
> +	asn_DEF_BIT_STRING_tags,	/* Same as above */
> +	sizeof(asn_DEF_BIT_STRING_tags)
> +	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	&asn_DEF_BIT_STRING_specs
> +};
> +
> +/*
> + * BIT STRING generic constraint.
> + */
> +int
> +BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
> +		asn_app_constraint_failed_f *ctfailcb, void
> *app_key) {
> +	const BIT_STRING_t *st =3D (const BIT_STRING_t *)sptr;
> +
> +	if(st && st->buf) {
> +		if((st->size =3D=3D 0 && st->bits_unused)
> +		|| st->bits_unused < 0 || st->bits_unused > 7) {
> +			ASN__CTFAIL(app_key, td, sptr,
> +				"%s: invalid padding byte (%s:%d)",
> +				td->name, __FILE__, __LINE__);
> +			return -1;
> +		}
> +	} else {
> +		ASN__CTFAIL(app_key, td, sptr,
> +			"%s: value not given (%s:%d)",
> +			td->name, __FILE__, __LINE__);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static char *_bit_pattern[16] =3D {
> +	"0000", "0001", "0010", "0011", "0100", "0101", "0110",
> "0111",
> +	"1000", "1001", "1010", "1011", "1100", "1101", "1110",
> "1111" +};
> +
> +asn_enc_rval_t
> +BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
> +	int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	asn_enc_rval_t er;
> +	char scratch[128];
> +	char *p =3D scratch;
> +	char *scend =3D scratch + (sizeof(scratch) - 10);
> +	const BIT_STRING_t *st =3D (const BIT_STRING_t *)sptr;
> +	int xcan =3D (flags & XER_F_CANONICAL);
> +	uint8_t *buf;
> +	uint8_t *end;
> +
> +	if(!st || !st->buf)
> +		ASN__ENCODE_FAILED;
> +
> +	er.encoded =3D 0;
> +
> +	buf =3D st->buf;
> +	end =3D buf + st->size - 1;	/* Last byte is special */
> +
> +	/*
> +	 * Binary dump
> +	 */
> +	for(; buf < end; buf++) {
> +		int v =3D *buf;
> +		int nline =3D xcan?0:(((buf - st->buf) % 8) =3D=3D 0);
> +		if(p >=3D scend || nline) {
> +			er.encoded +=3D p - scratch;
> +			ASN__CALLBACK(scratch, p - scratch);
> +			p =3D scratch;
> +			if(nline) ASN__TEXT_INDENT(1, ilevel);
> +		}
> +		memcpy(p + 0, _bit_pattern[v >> 4], 4);
> +		memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
> +		p +=3D 8;
> +	}
> +
> +	if(!xcan && ((buf - st->buf) % 8) =3D=3D 0)
> +		ASN__TEXT_INDENT(1, ilevel);
> +	er.encoded +=3D p - scratch;
> +	ASN__CALLBACK(scratch, p - scratch);
> +	p =3D scratch;
> +
> +	if(buf =3D=3D end) {
> +		int v =3D *buf;
> +		int ubits =3D st->bits_unused;
> +		int i;
> +		for(i =3D 7; i >=3D ubits; i--)
> +			*p++ =3D (v & (1 << i)) ? 0x31 : 0x30;
> +		er.encoded +=3D p - scratch;
> +		ASN__CALLBACK(scratch, p - scratch);
> +	}
> +
> +	if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
> +
> +	ASN__ENCODED_OK(er);
> +cb_failed:
> +	ASN__ENCODE_FAILED;
> +}
> +
> +
> +/*
> + * BIT STRING specific contents printer.
> + */
> +int
> +BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int
> ilevel,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	const char * const h2c =3D "0123456789ABCDEF";
> +	char scratch[64];
> +	const BIT_STRING_t *st =3D (const BIT_STRING_t *)sptr;
> +	uint8_t *buf;
> +	uint8_t *end;
> +	char *p =3D scratch;
> +
> +	(void)td;	/* Unused argument */
> +
> +	if(!st || !st->buf)
> +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
> +
> +	ilevel++;
> +	buf =3D st->buf;
> +	end =3D buf + st->size;
> +
> +	/*
> +	 * Hexadecimal dump.
> +	 */
> +	for(; buf < end; buf++) {
> +		if((buf - st->buf) % 16 =3D=3D 0 && (st->size > 16)
> +				&& buf !=3D st->buf) {
> +			_i_INDENT(1);
> +			/* Dump the string */
> +			if(cb(scratch, p - scratch, app_key) < 0)
> return -1;
> +			p =3D scratch;
> +		}
> +		*p++ =3D h2c[*buf >> 4];
> +		*p++ =3D h2c[*buf & 0x0F];
> +		*p++ =3D 0x20;
> +	}
> +
> +	if(p > scratch) {
> +		p--;	/* Eat the tailing space */
> +
> +		if((st->size > 16)) {
> +			_i_INDENT(1);
> +		}
> +
> +		/* Dump the incomplete 16-bytes row */
> +		if(cb(scratch, p - scratch, app_key) < 0)
> +			return -1;
> +	}
> +
> +	return 0;
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/BIT_STRING.h
> b/libkmod/pkcs7/asn1c-gen/BIT_STRING.h new file mode 100644
> index 000000000000..732e878bcad1
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/BIT_STRING.h
> @@ -0,0 +1,33 @@
> +/*-
> + * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	_BIT_STRING_H_
> +#define	_BIT_STRING_H_
> +
> +#include <OCTET_STRING.h>	/* Some help from OCTET STRING */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef struct BIT_STRING_s {
> +	uint8_t *buf;	/* BIT STRING body */
> +	int size;	/* Size of the above buffer */
> +
> +	int bits_unused;/* Unused trailing bits in the last octet
> (0..7) */ +
> +	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer
> boundaries */ +} BIT_STRING_t;
> +
> +extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING;
> +
> +asn_struct_print_f BIT_STRING_print;	/* Human-readable output
> */ +asn_constr_check_f BIT_STRING_constraint;
> +xer_type_encoder_f BIT_STRING_encode_xer;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _BIT_STRING_H_ */
> diff --git a/libkmod/pkcs7/asn1c-gen/CRLSequence.c
> b/libkmod/pkcs7/asn1c-gen/CRLSequence.c new file mode 100644
> index 000000000000..555425c270a3
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/CRLSequence.c
> @@ -0,0 +1,52 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "CRLSequence.h"
> +
> +static asn_TYPE_member_t asn_MBR_CRLSequence_1[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_CertificateList,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_CRLSequence_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_CRLSequence_specs_1 =3D {
> +	sizeof(struct CRLSequence),
> +	offsetof(struct CRLSequence, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +asn_TYPE_descriptor_t asn_DEF_CRLSequence =3D {
> +	"CRLSequence",
> +	"CRLSequence",
> +	SEQUENCE_OF_free,
> +	SEQUENCE_OF_print,
> +	SEQUENCE_OF_constraint,
> +	SEQUENCE_OF_decode_ber,
> +	SEQUENCE_OF_encode_der,
> +	SEQUENCE_OF_decode_xer,
> +	SEQUENCE_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_CRLSequence_tags_1,
> +	sizeof(asn_DEF_CRLSequence_tags_1)
> +		/sizeof(asn_DEF_CRLSequence_tags_1[0]), /* 1 */
> +	asn_DEF_CRLSequence_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_CRLSequence_tags_1)
> +		/sizeof(asn_DEF_CRLSequence_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_CRLSequence_1,
> +	1,	/* Single element */
> +	&asn_SPC_CRLSequence_specs_1	/* Additional specs */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/CRLSequence.h
> b/libkmod/pkcs7/asn1c-gen/CRLSequence.h new file mode 100644
> index 000000000000..8e64d30642f8
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/CRLSequence.h
> @@ -0,0 +1,44 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_CRLSequence_H_
> +#define	_CRLSequence_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <asn_SEQUENCE_OF.h>
> +#include <constr_SEQUENCE_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Forward declarations */
> +struct CertificateList;
> +
> +/* CRLSequence */
> +typedef struct CRLSequence {
> +	A_SEQUENCE_OF(struct CertificateList) list;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} CRLSequence_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_CRLSequence;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +/* Referred external types */
> +#include "CertificateList.h"
> +
> +#endif	/* _CRLSequence_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/Certificate.c
> b/libkmod/pkcs7/asn1c-gen/Certificate.c new file mode 100644
> index 000000000000..2216797c4447
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Certificate.c
> @@ -0,0 +1,104 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "Certificate.h"
> +
> +int
> +Certificate_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
> +			asn_app_constraint_failed_f *ctfailcb, void
> *app_key) {
> +	/* Replace with underlying type checker */
> +	td->check_constraints =3D asn_DEF_ANY.check_constraints;
> +	return td->check_constraints(td, sptr, ctfailcb, app_key);
> +}
> +
> +/*
> + * This type is implemented using ANY,
> + * so here we adjust the DEF accordingly.
> + */
> +static void
> +Certificate_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
> +	td->free_struct    =3D asn_DEF_ANY.free_struct;
> +	td->print_struct   =3D asn_DEF_ANY.print_struct;
> +	td->check_constraints =3D asn_DEF_ANY.check_constraints;
> +	td->ber_decoder    =3D asn_DEF_ANY.ber_decoder;
> +	td->der_encoder    =3D asn_DEF_ANY.der_encoder;
> +	td->xer_decoder    =3D asn_DEF_ANY.xer_decoder;
> +	td->xer_encoder    =3D asn_DEF_ANY.xer_encoder;
> +	td->uper_decoder   =3D asn_DEF_ANY.uper_decoder;
> +	td->uper_encoder   =3D asn_DEF_ANY.uper_encoder;
> +	if(!td->per_constraints)
> +		td->per_constraints =3D asn_DEF_ANY.per_constraints;
> +	td->elements       =3D asn_DEF_ANY.elements;
> +	td->elements_count =3D asn_DEF_ANY.elements_count;
> +	td->specifics      =3D asn_DEF_ANY.specifics;
> +}
> +
> +void
> +Certificate_free(asn_TYPE_descriptor_t *td,
> +		void *struct_ptr, int contents_only) {
> +	Certificate_1_inherit_TYPE_descriptor(td);
> +	td->free_struct(td, struct_ptr, contents_only);
> +}
> +
> +int
> +Certificate_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
> +		int ilevel, asn_app_consume_bytes_f *cb, void
> *app_key) {
> +	Certificate_1_inherit_TYPE_descriptor(td);
> +	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
> +}
> +
> +asn_dec_rval_t
> +Certificate_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const void *bufptr, size_t size,
> int tag_mode) {
> +	Certificate_1_inherit_TYPE_descriptor(td);
> +	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr,
> size, tag_mode); +}
> +
> +asn_enc_rval_t
> +Certificate_encode_der(asn_TYPE_descriptor_t *td,
> +		void *structure, int tag_mode, ber_tlv_tag_t tag,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	Certificate_1_inherit_TYPE_descriptor(td);
> +	return td->der_encoder(td, structure, tag_mode, tag, cb,
> app_key); +}
> +
> +asn_dec_rval_t
> +Certificate_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const char *opt_mname, const void
> *bufptr, size_t size) {
> +	Certificate_1_inherit_TYPE_descriptor(td);
> +	return td->xer_decoder(opt_codec_ctx, td, structure,
> opt_mname, bufptr, size); +}
> +
> +asn_enc_rval_t
> +Certificate_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
> +		int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	Certificate_1_inherit_TYPE_descriptor(td);
> +	return td->xer_encoder(td, structure, ilevel, flags, cb,
> app_key); +}
> +
> +asn_TYPE_descriptor_t asn_DEF_Certificate =3D {
> +	"Certificate",
> +	"Certificate",
> +	Certificate_free,
> +	Certificate_print,
> +	Certificate_constraint,
> +	Certificate_decode_ber,
> +	Certificate_encode_der,
> +	Certificate_decode_xer,
> +	Certificate_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	0,	/* No effective tags (pointer) */
> +	0,	/* No effective tags (count) */
> +	0,	/* No tags (pointer) */
> +	0,	/* No tags (count) */
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/Certificate.h
> b/libkmod/pkcs7/asn1c-gen/Certificate.h new file mode 100644
> index 000000000000..e0229c021e16
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Certificate.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_Certificate_H_
> +#define	_Certificate_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <ANY.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Certificate */
> +typedef ANY_t	 Certificate_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_Certificate;
> +asn_struct_free_f Certificate_free;
> +asn_struct_print_f Certificate_print;
> +asn_constr_check_f Certificate_constraint;
> +ber_type_decoder_f Certificate_decode_ber;
> +der_type_encoder_f Certificate_encode_der;
> +xer_type_decoder_f Certificate_decode_xer;
> +xer_type_encoder_f Certificate_encode_xer;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _Certificate_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/CertificateList.c
> b/libkmod/pkcs7/asn1c-gen/CertificateList.c new file mode 100644
> index 000000000000..f9a2bd2a1b86
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/CertificateList.c
> @@ -0,0 +1,52 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "CertificateList.h"
> +
> +static asn_TYPE_member_t asn_MBR_CertificateList_1[] =3D {
> +	{ ATF_OPEN_TYPE | ATF_POINTER, 0, 0,
> +		-1 /* Ambiguous tag (ANY?) */,
> +		0,
> +		&asn_DEF_Certificate,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_CertificateList_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_CertificateList_specs_1 =3D {
> +	sizeof(struct CertificateList),
> +	offsetof(struct CertificateList, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +asn_TYPE_descriptor_t asn_DEF_CertificateList =3D {
> +	"CertificateList",
> +	"CertificateList",
> +	SEQUENCE_OF_free,
> +	SEQUENCE_OF_print,
> +	SEQUENCE_OF_constraint,
> +	SEQUENCE_OF_decode_ber,
> +	SEQUENCE_OF_encode_der,
> +	SEQUENCE_OF_decode_xer,
> +	SEQUENCE_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_CertificateList_tags_1,
> +	sizeof(asn_DEF_CertificateList_tags_1)
> +		/sizeof(asn_DEF_CertificateList_tags_1[0]), /* 1 */
> +	asn_DEF_CertificateList_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_CertificateList_tags_1)
> +		/sizeof(asn_DEF_CertificateList_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_CertificateList_1,
> +	1,	/* Single element */
> +	&asn_SPC_CertificateList_specs_1	/* Additional specs
> */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/CertificateList.h
> b/libkmod/pkcs7/asn1c-gen/CertificateList.h new file mode 100644
> index 000000000000..b391f4dfa45d
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/CertificateList.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_CertificateList_H_
> +#define	_CertificateList_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include "Certificate.h"
> +#include <asn_SEQUENCE_OF.h>
> +#include <constr_SEQUENCE_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* CertificateList */
> +typedef struct CertificateList {
> +	A_SEQUENCE_OF(Certificate_t) list;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} CertificateList_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_CertificateList;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _CertificateList_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c
> b/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c new file mode
> 100644 index 000000000000..1d4c387cec05
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.c
> @@ -0,0 +1,52 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "CertificateRevocationLists.h"
> +
> +static asn_TYPE_member_t asn_MBR_CertificateRevocationLists_1[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_CertificateList,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t
> asn_DEF_CertificateRevocationLists_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
> +};
> +static asn_SET_OF_specifics_t
> asn_SPC_CertificateRevocationLists_specs_1 =3D {
> +	sizeof(struct CertificateRevocationLists),
> +	offsetof(struct CertificateRevocationLists, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +asn_TYPE_descriptor_t asn_DEF_CertificateRevocationLists =3D {
> +	"CertificateRevocationLists",
> +	"CertificateRevocationLists",
> +	SET_OF_free,
> +	SET_OF_print,
> +	SET_OF_constraint,
> +	SET_OF_decode_ber,
> +	SET_OF_encode_der,
> +	SET_OF_decode_xer,
> +	SET_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_CertificateRevocationLists_tags_1,
> +	sizeof(asn_DEF_CertificateRevocationLists_tags_1)
> +		/sizeof(asn_DEF_CertificateRevocationLists_tags_1[0]), /*
> 1 */
> +	asn_DEF_CertificateRevocationLists_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_CertificateRevocationLists_tags_1)
> +		/sizeof(asn_DEF_CertificateRevocationLists_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_CertificateRevocationLists_1,
> +	1,	/* Single element */
> +	&asn_SPC_CertificateRevocationLists_specs_1	/*
> Additional specs */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h
> b/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h new file mode
> 100644 index 000000000000..064deea9d3e3
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/CertificateRevocationLists.h
> @@ -0,0 +1,44 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_CertificateRevocationLists_H_
> +#define	_CertificateRevocationLists_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <asn_SET_OF.h>
> +#include <constr_SET_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Forward declarations */
> +struct CertificateList;
> +
> +/* CertificateRevocationLists */
> +typedef struct CertificateRevocationLists {
> +	A_SET_OF(struct CertificateList) list;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} CertificateRevocationLists_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_CertificateRevocationLists;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +/* Referred external types */
> +#include "CertificateList.h"
> +
> +#endif	/* _CertificateRevocationLists_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c
> b/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c new file mode
> 100644 index 000000000000..c0cb62523f43
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.c
> @@ -0,0 +1,109 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "CertificateSerialNumber.h"
> +
> +int
> +CertificateSerialNumber_constraint(asn_TYPE_descriptor_t *td, const
> void *sptr,
> +			asn_app_constraint_failed_f *ctfailcb, void
> *app_key) {
> +	/* Replace with underlying type checker */
> +	td->check_constraints =3D asn_DEF_INTEGER.check_constraints;
> +	return td->check_constraints(td, sptr, ctfailcb, app_key);
> +}
> +
> +/*
> + * This type is implemented using INTEGER,
> + * so here we adjust the DEF accordingly.
> + */
> +static void
> +CertificateSerialNumber_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t
> *td) {
> +	td->free_struct    =3D asn_DEF_INTEGER.free_struct;
> +	td->print_struct   =3D asn_DEF_INTEGER.print_struct;
> +	td->check_constraints =3D asn_DEF_INTEGER.check_constraints;
> +	td->ber_decoder    =3D asn_DEF_INTEGER.ber_decoder;
> +	td->der_encoder    =3D asn_DEF_INTEGER.der_encoder;
> +	td->xer_decoder    =3D asn_DEF_INTEGER.xer_decoder;
> +	td->xer_encoder    =3D asn_DEF_INTEGER.xer_encoder;
> +	td->uper_decoder   =3D asn_DEF_INTEGER.uper_decoder;
> +	td->uper_encoder   =3D asn_DEF_INTEGER.uper_encoder;
> +	if(!td->per_constraints)
> +		td->per_constraints =3D
> asn_DEF_INTEGER.per_constraints;
> +	td->elements       =3D asn_DEF_INTEGER.elements;
> +	td->elements_count =3D asn_DEF_INTEGER.elements_count;
> +	td->specifics      =3D asn_DEF_INTEGER.specifics;
> +}
> +
> +void
> +CertificateSerialNumber_free(asn_TYPE_descriptor_t *td,
> +		void *struct_ptr, int contents_only) {
> +	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
> +	td->free_struct(td, struct_ptr, contents_only);
> +}
> +
> +int
> +CertificateSerialNumber_print(asn_TYPE_descriptor_t *td, const void
> *struct_ptr,
> +		int ilevel, asn_app_consume_bytes_f *cb, void
> *app_key) {
> +	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
> +	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
> +}
> +
> +asn_dec_rval_t
> +CertificateSerialNumber_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const void *bufptr, size_t size,
> int tag_mode) {
> +	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
> +	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr,
> size, tag_mode); +}
> +
> +asn_enc_rval_t
> +CertificateSerialNumber_encode_der(asn_TYPE_descriptor_t *td,
> +		void *structure, int tag_mode, ber_tlv_tag_t tag,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
> +	return td->der_encoder(td, structure, tag_mode, tag, cb,
> app_key); +}
> +
> +asn_dec_rval_t
> +CertificateSerialNumber_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const char *opt_mname, const void
> *bufptr, size_t size) {
> +	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
> +	return td->xer_decoder(opt_codec_ctx, td, structure,
> opt_mname, bufptr, size); +}
> +
> +asn_enc_rval_t
> +CertificateSerialNumber_encode_xer(asn_TYPE_descriptor_t *td, void
> *structure,
> +		int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	CertificateSerialNumber_1_inherit_TYPE_descriptor(td);
> +	return td->xer_encoder(td, structure, ilevel, flags, cb,
> app_key); +}
> +
> +static const ber_tlv_tag_t asn_DEF_CertificateSerialNumber_tags_1[]
> =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
> +};
> +asn_TYPE_descriptor_t asn_DEF_CertificateSerialNumber =3D {
> +	"CertificateSerialNumber",
> +	"CertificateSerialNumber",
> +	CertificateSerialNumber_free,
> +	CertificateSerialNumber_print,
> +	CertificateSerialNumber_constraint,
> +	CertificateSerialNumber_decode_ber,
> +	CertificateSerialNumber_encode_der,
> +	CertificateSerialNumber_decode_xer,
> +	CertificateSerialNumber_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_CertificateSerialNumber_tags_1,
> +	sizeof(asn_DEF_CertificateSerialNumber_tags_1)
> +		/sizeof(asn_DEF_CertificateSerialNumber_tags_1[0]), /*
> 1 */
> +	asn_DEF_CertificateSerialNumber_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_CertificateSerialNumber_tags_1)
> +		/sizeof(asn_DEF_CertificateSerialNumber_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h
> b/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h new file mode
> 100644 index 000000000000..b82390d40491
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/CertificateSerialNumber.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_CertificateSerialNumber_H_
> +#define	_CertificateSerialNumber_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <INTEGER.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* CertificateSerialNumber */
> +typedef INTEGER_t	 CertificateSerialNumber_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_CertificateSerialNumber;
> +asn_struct_free_f CertificateSerialNumber_free;
> +asn_struct_print_f CertificateSerialNumber_print;
> +asn_constr_check_f CertificateSerialNumber_constraint;
> +ber_type_decoder_f CertificateSerialNumber_decode_ber;
> +der_type_encoder_f CertificateSerialNumber_encode_der;
> +xer_type_decoder_f CertificateSerialNumber_decode_xer;
> +xer_type_encoder_f CertificateSerialNumber_encode_xer;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _CertificateSerialNumber_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/Certificates.c
> b/libkmod/pkcs7/asn1c-gen/Certificates.c new file mode 100644
> index 000000000000..46d885299683
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Certificates.c
> @@ -0,0 +1,52 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "Certificates.h"
> +
> +static asn_TYPE_member_t asn_MBR_Certificates_1[] =3D {
> +	{ ATF_OPEN_TYPE | ATF_POINTER, 0, 0,
> +		-1 /* Ambiguous tag (ANY?) */,
> +		0,
> +		&asn_DEF_Certificate,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_Certificates_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_Certificates_specs_1 =3D {
> +	sizeof(struct Certificates),
> +	offsetof(struct Certificates, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +asn_TYPE_descriptor_t asn_DEF_Certificates =3D {
> +	"Certificates",
> +	"Certificates",
> +	SEQUENCE_OF_free,
> +	SEQUENCE_OF_print,
> +	SEQUENCE_OF_constraint,
> +	SEQUENCE_OF_decode_ber,
> +	SEQUENCE_OF_encode_der,
> +	SEQUENCE_OF_decode_xer,
> +	SEQUENCE_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_Certificates_tags_1,
> +	sizeof(asn_DEF_Certificates_tags_1)
> +		/sizeof(asn_DEF_Certificates_tags_1[0]), /* 1 */
> +	asn_DEF_Certificates_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_Certificates_tags_1)
> +		/sizeof(asn_DEF_Certificates_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_Certificates_1,
> +	1,	/* Single element */
> +	&asn_SPC_Certificates_specs_1	/* Additional specs */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/Certificates.h
> b/libkmod/pkcs7/asn1c-gen/Certificates.h new file mode 100644
> index 000000000000..9ba77c12015e
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Certificates.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_Certificates_H_
> +#define	_Certificates_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include "Certificate.h"
> +#include <asn_SEQUENCE_OF.h>
> +#include <constr_SEQUENCE_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Certificates */
> +typedef struct Certificates {
> +	A_SEQUENCE_OF(Certificate_t) list;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} Certificates_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_Certificates;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _Certificates_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/ContentInfo.c
> b/libkmod/pkcs7/asn1c-gen/ContentInfo.c new file mode 100644
> index 000000000000..ba7a2f898ce2
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ContentInfo.c
> @@ -0,0 +1,69 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "ContentInfo.h"
> +
> +static asn_TYPE_member_t asn_MBR_ContentInfo_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct ContentInfo, contentType),
> +		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
> +		0,
> +		&asn_DEF_ContentType,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"contentType"
> +		},
> +	{ ATF_POINTER, 1, offsetof(struct ContentInfo, content),
> +		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
> +		+1,	/* EXPLICIT tag at current level */
> +		&asn_DEF_Data,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"content"
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_ContentInfo_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static const asn_TYPE_tag2member_t asn_MAP_ContentInfo_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /*
> contentType */
> +    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, 0, 0 } /* content */
> +};
> +static asn_SEQUENCE_specifics_t asn_SPC_ContentInfo_specs_1 =3D {
> +	sizeof(struct ContentInfo),
> +	offsetof(struct ContentInfo, _asn_ctx),
> +	asn_MAP_ContentInfo_tag2el_1,
> +	2,	/* Count of tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_ContentInfo =3D {
> +	"ContentInfo",
> +	"ContentInfo",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_ContentInfo_tags_1,
> +	sizeof(asn_DEF_ContentInfo_tags_1)
> +		/sizeof(asn_DEF_ContentInfo_tags_1[0]), /* 1 */
> +	asn_DEF_ContentInfo_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_ContentInfo_tags_1)
> +		/sizeof(asn_DEF_ContentInfo_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_ContentInfo_1,
> +	2,	/* Elements count */
> +	&asn_SPC_ContentInfo_specs_1	/* Additional specs */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/ContentInfo.h
> b/libkmod/pkcs7/asn1c-gen/ContentInfo.h new file mode 100644
> index 000000000000..c0d2f8a2d6bb
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ContentInfo.h
> @@ -0,0 +1,40 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_ContentInfo_H_
> +#define	_ContentInfo_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include "ContentType.h"
> +#include "Data.h"
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* ContentInfo */
> +typedef struct ContentInfo {
> +	ContentType_t	 contentType;
> +	Data_t	*content	/* OPTIONAL */;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} ContentInfo_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_ContentInfo;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _ContentInfo_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/ContentType.c
> b/libkmod/pkcs7/asn1c-gen/ContentType.c new file mode 100644
> index 000000000000..c7d4b19973d6
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ContentType.c
> @@ -0,0 +1,109 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "ContentType.h"
> +
> +int
> +ContentType_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
> +			asn_app_constraint_failed_f *ctfailcb, void
> *app_key) {
> +	/* Replace with underlying type checker */
> +	td->check_constraints =3D
> asn_DEF_OBJECT_IDENTIFIER.check_constraints;
> +	return td->check_constraints(td, sptr, ctfailcb, app_key);
> +}
> +
> +/*
> + * This type is implemented using OBJECT_IDENTIFIER,
> + * so here we adjust the DEF accordingly.
> + */
> +static void
> +ContentType_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
> +	td->free_struct    =3D asn_DEF_OBJECT_IDENTIFIER.free_struct;
> +	td->print_struct   =3D asn_DEF_OBJECT_IDENTIFIER.print_struct;
> +	td->check_constraints =3D
> asn_DEF_OBJECT_IDENTIFIER.check_constraints;
> +	td->ber_decoder    =3D asn_DEF_OBJECT_IDENTIFIER.ber_decoder;
> +	td->der_encoder    =3D asn_DEF_OBJECT_IDENTIFIER.der_encoder;
> +	td->xer_decoder    =3D asn_DEF_OBJECT_IDENTIFIER.xer_decoder;
> +	td->xer_encoder    =3D asn_DEF_OBJECT_IDENTIFIER.xer_encoder;
> +	td->uper_decoder   =3D asn_DEF_OBJECT_IDENTIFIER.uper_decoder;
> +	td->uper_encoder   =3D asn_DEF_OBJECT_IDENTIFIER.uper_encoder;
> +	if(!td->per_constraints)
> +		td->per_constraints =3D
> asn_DEF_OBJECT_IDENTIFIER.per_constraints;
> +	td->elements       =3D asn_DEF_OBJECT_IDENTIFIER.elements;
> +	td->elements_count =3D
> asn_DEF_OBJECT_IDENTIFIER.elements_count;
> +	td->specifics      =3D asn_DEF_OBJECT_IDENTIFIER.specifics;
> +}
> +
> +void
> +ContentType_free(asn_TYPE_descriptor_t *td,
> +		void *struct_ptr, int contents_only) {
> +	ContentType_1_inherit_TYPE_descriptor(td);
> +	td->free_struct(td, struct_ptr, contents_only);
> +}
> +
> +int
> +ContentType_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
> +		int ilevel, asn_app_consume_bytes_f *cb, void
> *app_key) {
> +	ContentType_1_inherit_TYPE_descriptor(td);
> +	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
> +}
> +
> +asn_dec_rval_t
> +ContentType_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const void *bufptr, size_t size,
> int tag_mode) {
> +	ContentType_1_inherit_TYPE_descriptor(td);
> +	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr,
> size, tag_mode); +}
> +
> +asn_enc_rval_t
> +ContentType_encode_der(asn_TYPE_descriptor_t *td,
> +		void *structure, int tag_mode, ber_tlv_tag_t tag,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	ContentType_1_inherit_TYPE_descriptor(td);
> +	return td->der_encoder(td, structure, tag_mode, tag, cb,
> app_key); +}
> +
> +asn_dec_rval_t
> +ContentType_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const char *opt_mname, const void
> *bufptr, size_t size) {
> +	ContentType_1_inherit_TYPE_descriptor(td);
> +	return td->xer_decoder(opt_codec_ctx, td, structure,
> opt_mname, bufptr, size); +}
> +
> +asn_enc_rval_t
> +ContentType_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
> +		int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	ContentType_1_inherit_TYPE_descriptor(td);
> +	return td->xer_encoder(td, structure, ilevel, flags, cb,
> app_key); +}
> +
> +static const ber_tlv_tag_t asn_DEF_ContentType_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (6 << 2))
> +};
> +asn_TYPE_descriptor_t asn_DEF_ContentType =3D {
> +	"ContentType",
> +	"ContentType",
> +	ContentType_free,
> +	ContentType_print,
> +	ContentType_constraint,
> +	ContentType_decode_ber,
> +	ContentType_encode_der,
> +	ContentType_decode_xer,
> +	ContentType_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_ContentType_tags_1,
> +	sizeof(asn_DEF_ContentType_tags_1)
> +		/sizeof(asn_DEF_ContentType_tags_1[0]), /* 1 */
> +	asn_DEF_ContentType_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_ContentType_tags_1)
> +		/sizeof(asn_DEF_ContentType_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/ContentType.h
> b/libkmod/pkcs7/asn1c-gen/ContentType.h new file mode 100644
> index 000000000000..fd47de6f6c7f
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ContentType.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_ContentType_H_
> +#define	_ContentType_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <OBJECT_IDENTIFIER.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* ContentType */
> +typedef OBJECT_IDENTIFIER_t	 ContentType_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_ContentType;
> +asn_struct_free_f ContentType_free;
> +asn_struct_print_f ContentType_print;
> +asn_constr_check_f ContentType_constraint;
> +ber_type_decoder_f ContentType_decode_ber;
> +der_type_encoder_f ContentType_encode_der;
> +xer_type_decoder_f ContentType_decode_xer;
> +xer_type_encoder_f ContentType_encode_xer;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _ContentType_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/Data.c
> b/libkmod/pkcs7/asn1c-gen/Data.c new file mode 100644
> index 000000000000..d158bf5f30fc
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Data.c
> @@ -0,0 +1,104 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "Data.h"
> +
> +int
> +Data_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
> +			asn_app_constraint_failed_f *ctfailcb, void
> *app_key) {
> +	/* Replace with underlying type checker */
> +	td->check_constraints =3D asn_DEF_ANY.check_constraints;
> +	return td->check_constraints(td, sptr, ctfailcb, app_key);
> +}
> +
> +/*
> + * This type is implemented using ANY,
> + * so here we adjust the DEF accordingly.
> + */
> +static void
> +Data_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
> +	td->free_struct    =3D asn_DEF_ANY.free_struct;
> +	td->print_struct   =3D asn_DEF_ANY.print_struct;
> +	td->check_constraints =3D asn_DEF_ANY.check_constraints;
> +	td->ber_decoder    =3D asn_DEF_ANY.ber_decoder;
> +	td->der_encoder    =3D asn_DEF_ANY.der_encoder;
> +	td->xer_decoder    =3D asn_DEF_ANY.xer_decoder;
> +	td->xer_encoder    =3D asn_DEF_ANY.xer_encoder;
> +	td->uper_decoder   =3D asn_DEF_ANY.uper_decoder;
> +	td->uper_encoder   =3D asn_DEF_ANY.uper_encoder;
> +	if(!td->per_constraints)
> +		td->per_constraints =3D asn_DEF_ANY.per_constraints;
> +	td->elements       =3D asn_DEF_ANY.elements;
> +	td->elements_count =3D asn_DEF_ANY.elements_count;
> +	td->specifics      =3D asn_DEF_ANY.specifics;
> +}
> +
> +void
> +Data_free(asn_TYPE_descriptor_t *td,
> +		void *struct_ptr, int contents_only) {
> +	Data_1_inherit_TYPE_descriptor(td);
> +	td->free_struct(td, struct_ptr, contents_only);
> +}
> +
> +int
> +Data_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
> +		int ilevel, asn_app_consume_bytes_f *cb, void
> *app_key) {
> +	Data_1_inherit_TYPE_descriptor(td);
> +	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
> +}
> +
> +asn_dec_rval_t
> +Data_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const void *bufptr, size_t size,
> int tag_mode) {
> +	Data_1_inherit_TYPE_descriptor(td);
> +	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr,
> size, tag_mode); +}
> +
> +asn_enc_rval_t
> +Data_encode_der(asn_TYPE_descriptor_t *td,
> +		void *structure, int tag_mode, ber_tlv_tag_t tag,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	Data_1_inherit_TYPE_descriptor(td);
> +	return td->der_encoder(td, structure, tag_mode, tag, cb,
> app_key); +}
> +
> +asn_dec_rval_t
> +Data_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const char *opt_mname, const void
> *bufptr, size_t size) {
> +	Data_1_inherit_TYPE_descriptor(td);
> +	return td->xer_decoder(opt_codec_ctx, td, structure,
> opt_mname, bufptr, size); +}
> +
> +asn_enc_rval_t
> +Data_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
> +		int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	Data_1_inherit_TYPE_descriptor(td);
> +	return td->xer_encoder(td, structure, ilevel, flags, cb,
> app_key); +}
> +
> +asn_TYPE_descriptor_t asn_DEF_Data =3D {
> +	"Data",
> +	"Data",
> +	Data_free,
> +	Data_print,
> +	Data_constraint,
> +	Data_decode_ber,
> +	Data_encode_der,
> +	Data_decode_xer,
> +	Data_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	0,	/* No effective tags (pointer) */
> +	0,	/* No effective tags (count) */
> +	0,	/* No tags (pointer) */
> +	0,	/* No tags (count) */
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/Data.h
> b/libkmod/pkcs7/asn1c-gen/Data.h new file mode 100644
> index 000000000000..314729dbdec3
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Data.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_Data_H_
> +#define	_Data_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <ANY.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Data */
> +typedef ANY_t	 Data_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_Data;
> +asn_struct_free_f Data_free;
> +asn_struct_print_f Data_print;
> +asn_constr_check_f Data_constraint;
> +ber_type_decoder_f Data_decode_ber;
> +der_type_encoder_f Data_encode_der;
> +xer_type_decoder_f Data_decode_xer;
> +xer_type_encoder_f Data_encode_xer;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _Data_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c
> b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c new file mode
> 100644 index 000000000000..fc56ff9337ce
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.c
> @@ -0,0 +1,68 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "DigestAlgorithmIdentifier.h"
> +
> +static asn_TYPE_member_t asn_MBR_DigestAlgorithmIdentifier_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct DigestAlgorithmIdentifier,
> algorithm),
> +		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
> +		0,
> +		&asn_DEF_OBJECT_IDENTIFIER,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"algorithm"
> +		},
> +	{ ATF_OPEN_TYPE | ATF_POINTER, 1, offsetof(struct
> DigestAlgorithmIdentifier, parameters),
> +		-1 /* Ambiguous tag (ANY?) */,
> +		0,
> +		&asn_DEF_ANY,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"parameters"
> +		},
> +};
> +static const ber_tlv_tag_t
> asn_DEF_DigestAlgorithmIdentifier_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_DigestAlgorithmIdentifier_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 } /* algorithm */
> +};
> +static asn_SEQUENCE_specifics_t
> asn_SPC_DigestAlgorithmIdentifier_specs_1 =3D {
> +	sizeof(struct DigestAlgorithmIdentifier),
> +	offsetof(struct DigestAlgorithmIdentifier, _asn_ctx),
> +	asn_MAP_DigestAlgorithmIdentifier_tag2el_1,
> +	1,	/* Count of tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_DigestAlgorithmIdentifier =3D {
> +	"DigestAlgorithmIdentifier",
> +	"DigestAlgorithmIdentifier",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_DigestAlgorithmIdentifier_tags_1,
> +	sizeof(asn_DEF_DigestAlgorithmIdentifier_tags_1)
> +		/sizeof(asn_DEF_DigestAlgorithmIdentifier_tags_1[0]), /*
> 1 */
> +	asn_DEF_DigestAlgorithmIdentifier_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_DigestAlgorithmIdentifier_tags_1)
> +		/sizeof(asn_DEF_DigestAlgorithmIdentifier_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_DigestAlgorithmIdentifier_1,
> +	2,	/* Elements count */
> +	&asn_SPC_DigestAlgorithmIdentifier_specs_1	/*
> Additional specs */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h
> b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h new file mode
> 100644 index 000000000000..92e726c2922e
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifier.h
> @@ -0,0 +1,40 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_DigestAlgorithmIdentifier_H_
> +#define	_DigestAlgorithmIdentifier_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <OBJECT_IDENTIFIER.h>
> +#include <ANY.h>
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* DigestAlgorithmIdentifier */
> +typedef struct DigestAlgorithmIdentifier {
> +	OBJECT_IDENTIFIER_t	 algorithm;
> +	ANY_t	*parameters	/* OPTIONAL */;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} DigestAlgorithmIdentifier_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_DigestAlgorithmIdentifier;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _DigestAlgorithmIdentifier_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c
> b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c new file mode
> 100644 index 000000000000..3b0ffd27c891
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.c
> @@ -0,0 +1,153 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "DigestAlgorithmIdentifiers.h"
> +
> +static asn_TYPE_member_t asn_MBR_daSet_2[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_DigestAlgorithmIdentifier,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_daSet_tags_2[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_daSet_specs_2 =3D {
> +	sizeof(struct daSet),
> +	offsetof(struct daSet, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_daSet_2 =3D {
> +	"daSet",
> +	"daSet",
> +	SET_OF_free,
> +	SET_OF_print,
> +	SET_OF_constraint,
> +	SET_OF_decode_ber,
> +	SET_OF_encode_der,
> +	SET_OF_decode_xer,
> +	SET_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_daSet_tags_2,
> +	sizeof(asn_DEF_daSet_tags_2)
> +		/sizeof(asn_DEF_daSet_tags_2[0]), /* 1 */
> +	asn_DEF_daSet_tags_2,	/* Same as above */
> +	sizeof(asn_DEF_daSet_tags_2)
> +		/sizeof(asn_DEF_daSet_tags_2[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_daSet_2,
> +	1,	/* Single element */
> +	&asn_SPC_daSet_specs_2	/* Additional specs */
> +};
> +
> +static asn_TYPE_member_t asn_MBR_daSequence_4[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_DigestAlgorithmIdentifier,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_daSequence_tags_4[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_daSequence_specs_4 =3D {
> +	sizeof(struct daSequence),
> +	offsetof(struct daSequence, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_daSequence_4 =3D {
> +	"daSequence",
> +	"daSequence",
> +	SEQUENCE_OF_free,
> +	SEQUENCE_OF_print,
> +	SEQUENCE_OF_constraint,
> +	SEQUENCE_OF_decode_ber,
> +	SEQUENCE_OF_encode_der,
> +	SEQUENCE_OF_decode_xer,
> +	SEQUENCE_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_daSequence_tags_4,
> +	sizeof(asn_DEF_daSequence_tags_4)
> +		/sizeof(asn_DEF_daSequence_tags_4[0]), /* 1 */
> +	asn_DEF_daSequence_tags_4,	/* Same as above */
> +	sizeof(asn_DEF_daSequence_tags_4)
> +		/sizeof(asn_DEF_daSequence_tags_4[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_daSequence_4,
> +	1,	/* Single element */
> +	&asn_SPC_daSequence_specs_4	/* Additional specs */
> +};
> +
> +static asn_TYPE_member_t asn_MBR_DigestAlgorithmIdentifiers_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct
> DigestAlgorithmIdentifiers, choice.daSet),
> +		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
> +		0,
> +		&asn_DEF_daSet_2,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"daSet"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct
> DigestAlgorithmIdentifiers, choice.daSequence),
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_daSequence_4,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"daSequence"
> +		},
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_DigestAlgorithmIdentifiers_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 0 }, /*
> daSequence */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 0, 0, 0 } /* daSet */
> +};
> +static asn_CHOICE_specifics_t
> asn_SPC_DigestAlgorithmIdentifiers_specs_1 =3D {
> +	sizeof(struct DigestAlgorithmIdentifiers),
> +	offsetof(struct DigestAlgorithmIdentifiers, _asn_ctx),
> +	offsetof(struct DigestAlgorithmIdentifiers, present),
> +	sizeof(((struct DigestAlgorithmIdentifiers *)0)->present),
> +	asn_MAP_DigestAlgorithmIdentifiers_tag2el_1,
> +	2,	/* Count of tags in the map */
> +	0,
> +	-1	/* Extensions start */
> +};
> +asn_TYPE_descriptor_t asn_DEF_DigestAlgorithmIdentifiers =3D {
> +	"DigestAlgorithmIdentifiers",
> +	"DigestAlgorithmIdentifiers",
> +	CHOICE_free,
> +	CHOICE_print,
> +	CHOICE_constraint,
> +	CHOICE_decode_ber,
> +	CHOICE_encode_der,
> +	CHOICE_decode_xer,
> +	CHOICE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	CHOICE_outmost_tag,
> +	0,	/* No effective tags (pointer) */
> +	0,	/* No effective tags (count) */
> +	0,	/* No tags (pointer) */
> +	0,	/* No tags (count) */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_DigestAlgorithmIdentifiers_1,
> +	2,	/* Elements count */
> +	&asn_SPC_DigestAlgorithmIdentifiers_specs_1	/*
> Additional specs */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h
> b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h new file mode
> 100644 index 000000000000..dc90d321db1a
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/DigestAlgorithmIdentifiers.h
> @@ -0,0 +1,68 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_DigestAlgorithmIdentifiers_H_
> +#define	_DigestAlgorithmIdentifiers_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <asn_SET_OF.h>
> +#include <constr_SET_OF.h>
> +#include <asn_SEQUENCE_OF.h>
> +#include <constr_SEQUENCE_OF.h>
> +#include <constr_CHOICE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Dependencies */
> +typedef enum DigestAlgorithmIdentifiers_PR {
> +	DigestAlgorithmIdentifiers_PR_NOTHING,	/* No
> components present */
> +	DigestAlgorithmIdentifiers_PR_daSet,
> +	DigestAlgorithmIdentifiers_PR_daSequence
> +} DigestAlgorithmIdentifiers_PR;
> +
> +/* Forward declarations */
> +struct DigestAlgorithmIdentifier;
> +
> +/* DigestAlgorithmIdentifiers */
> +typedef struct DigestAlgorithmIdentifiers {
> +	DigestAlgorithmIdentifiers_PR present;
> +	union DigestAlgorithmIdentifiers_u {
> +		struct daSet {
> +			A_SET_OF(struct DigestAlgorithmIdentifier)
> list;
> +		=09
> +			/* Context for parsing across buffer
> boundaries */
> +			asn_struct_ctx_t _asn_ctx;
> +		} daSet;
> +		struct daSequence {
> +			A_SEQUENCE_OF(struct
> DigestAlgorithmIdentifier) list;
> +		=09
> +			/* Context for parsing across buffer
> boundaries */
> +			asn_struct_ctx_t _asn_ctx;
> +		} daSequence;
> +	} choice;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} DigestAlgorithmIdentifiers_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_DigestAlgorithmIdentifiers;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +/* Referred external types */
> +#include "DigestAlgorithmIdentifier.h"
> +
> +#endif	/* _DigestAlgorithmIdentifiers_H_ */
> +#include <asn_internal.h>
> diff --git
> a/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c
> b/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c new
> file mode 100644 index 000000000000..bccf7fe4677e --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.c
> @@ -0,0 +1,68 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "DigestEncryptionAlgorithmIdentifier.h"
> +
> +static asn_TYPE_member_t
> asn_MBR_DigestEncryptionAlgorithmIdentifier_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct
> DigestEncryptionAlgorithmIdentifier, algorithm),
> +		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
> +		0,
> +		&asn_DEF_OBJECT_IDENTIFIER,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"algorithm"
> +		},
> +	{ ATF_OPEN_TYPE | ATF_POINTER, 1, offsetof(struct
> DigestEncryptionAlgorithmIdentifier, parameters),
> +		-1 /* Ambiguous tag (ANY?) */,
> +		0,
> +		&asn_DEF_ANY,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"parameters"
> +		},
> +};
> +static const ber_tlv_tag_t
> asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_DigestEncryptionAlgorithmIdentifier_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 } /* algorithm */
> +};
> +static asn_SEQUENCE_specifics_t
> asn_SPC_DigestEncryptionAlgorithmIdentifier_specs_1 =3D {
> +	sizeof(struct DigestEncryptionAlgorithmIdentifier),
> +	offsetof(struct DigestEncryptionAlgorithmIdentifier,
> _asn_ctx),
> +	asn_MAP_DigestEncryptionAlgorithmIdentifier_tag2el_1,
> +	1,	/* Count of tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_DigestEncryptionAlgorithmIdentifier =3D {
> +	"DigestEncryptionAlgorithmIdentifier",
> +	"DigestEncryptionAlgorithmIdentifier",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1,
> +	sizeof(asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1)
> +		/sizeof(asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1[0]), /*
> 1 */
> +
> asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1)
> +		/sizeof(asn_DEF_DigestEncryptionAlgorithmIdentifier_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_DigestEncryptionAlgorithmIdentifier_1,
> +	2,	/* Elements count */
> +
> &asn_SPC_DigestEncryptionAlgorithmIdentifier_specs_1	/*
> Additional specs */ +}; +
> diff --git
> a/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h
> b/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h new
> file mode 100644 index 000000000000..d06354b07a75 --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/DigestEncryptionAlgorithmIdentifier.h
> @@ -0,0 +1,40 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_DigestEncryptionAlgorithmIdentifier_H_
> +#define	_DigestEncryptionAlgorithmIdentifier_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <OBJECT_IDENTIFIER.h>
> +#include <ANY.h>
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* DigestEncryptionAlgorithmIdentifier */
> +typedef struct DigestEncryptionAlgorithmIdentifier {
> +	OBJECT_IDENTIFIER_t	 algorithm;
> +	ANY_t	*parameters	/* OPTIONAL */;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} DigestEncryptionAlgorithmIdentifier_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t
> asn_DEF_DigestEncryptionAlgorithmIdentifier; +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _DigestEncryptionAlgorithmIdentifier_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/EncryptedDigest.c
> b/libkmod/pkcs7/asn1c-gen/EncryptedDigest.c new file mode 100644
> index 000000000000..37a36e4ee3ed
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/EncryptedDigest.c
> @@ -0,0 +1,109 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "EncryptedDigest.h"
> +
> +int
> +EncryptedDigest_constraint(asn_TYPE_descriptor_t *td, const void
> *sptr,
> +			asn_app_constraint_failed_f *ctfailcb, void
> *app_key) {
> +	/* Replace with underlying type checker */
> +	td->check_constraints =3D
> asn_DEF_OCTET_STRING.check_constraints;
> +	return td->check_constraints(td, sptr, ctfailcb, app_key);
> +}
> +
> +/*
> + * This type is implemented using OCTET_STRING,
> + * so here we adjust the DEF accordingly.
> + */
> +static void
> +EncryptedDigest_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td)
> {
> +	td->free_struct    =3D asn_DEF_OCTET_STRING.free_struct;
> +	td->print_struct   =3D asn_DEF_OCTET_STRING.print_struct;
> +	td->check_constraints =3D
> asn_DEF_OCTET_STRING.check_constraints;
> +	td->ber_decoder    =3D asn_DEF_OCTET_STRING.ber_decoder;
> +	td->der_encoder    =3D asn_DEF_OCTET_STRING.der_encoder;
> +	td->xer_decoder    =3D asn_DEF_OCTET_STRING.xer_decoder;
> +	td->xer_encoder    =3D asn_DEF_OCTET_STRING.xer_encoder;
> +	td->uper_decoder   =3D asn_DEF_OCTET_STRING.uper_decoder;
> +	td->uper_encoder   =3D asn_DEF_OCTET_STRING.uper_encoder;
> +	if(!td->per_constraints)
> +		td->per_constraints =3D
> asn_DEF_OCTET_STRING.per_constraints;
> +	td->elements       =3D asn_DEF_OCTET_STRING.elements;
> +	td->elements_count =3D asn_DEF_OCTET_STRING.elements_count;
> +	td->specifics      =3D asn_DEF_OCTET_STRING.specifics;
> +}
> +
> +void
> +EncryptedDigest_free(asn_TYPE_descriptor_t *td,
> +		void *struct_ptr, int contents_only) {
> +	EncryptedDigest_1_inherit_TYPE_descriptor(td);
> +	td->free_struct(td, struct_ptr, contents_only);
> +}
> +
> +int
> +EncryptedDigest_print(asn_TYPE_descriptor_t *td, const void
> *struct_ptr,
> +		int ilevel, asn_app_consume_bytes_f *cb, void
> *app_key) {
> +	EncryptedDigest_1_inherit_TYPE_descriptor(td);
> +	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
> +}
> +
> +asn_dec_rval_t
> +EncryptedDigest_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const void *bufptr, size_t size,
> int tag_mode) {
> +	EncryptedDigest_1_inherit_TYPE_descriptor(td);
> +	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr,
> size, tag_mode); +}
> +
> +asn_enc_rval_t
> +EncryptedDigest_encode_der(asn_TYPE_descriptor_t *td,
> +		void *structure, int tag_mode, ber_tlv_tag_t tag,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	EncryptedDigest_1_inherit_TYPE_descriptor(td);
> +	return td->der_encoder(td, structure, tag_mode, tag, cb,
> app_key); +}
> +
> +asn_dec_rval_t
> +EncryptedDigest_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const char *opt_mname, const void
> *bufptr, size_t size) {
> +	EncryptedDigest_1_inherit_TYPE_descriptor(td);
> +	return td->xer_decoder(opt_codec_ctx, td, structure,
> opt_mname, bufptr, size); +}
> +
> +asn_enc_rval_t
> +EncryptedDigest_encode_xer(asn_TYPE_descriptor_t *td, void
> *structure,
> +		int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	EncryptedDigest_1_inherit_TYPE_descriptor(td);
> +	return td->xer_encoder(td, structure, ilevel, flags, cb,
> app_key); +}
> +
> +static const ber_tlv_tag_t asn_DEF_EncryptedDigest_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
> +};
> +asn_TYPE_descriptor_t asn_DEF_EncryptedDigest =3D {
> +	"EncryptedDigest",
> +	"EncryptedDigest",
> +	EncryptedDigest_free,
> +	EncryptedDigest_print,
> +	EncryptedDigest_constraint,
> +	EncryptedDigest_decode_ber,
> +	EncryptedDigest_encode_der,
> +	EncryptedDigest_decode_xer,
> +	EncryptedDigest_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_EncryptedDigest_tags_1,
> +	sizeof(asn_DEF_EncryptedDigest_tags_1)
> +		/sizeof(asn_DEF_EncryptedDigest_tags_1[0]), /* 1 */
> +	asn_DEF_EncryptedDigest_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_EncryptedDigest_tags_1)
> +		/sizeof(asn_DEF_EncryptedDigest_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/EncryptedDigest.h
> b/libkmod/pkcs7/asn1c-gen/EncryptedDigest.h new file mode 100644
> index 000000000000..7c202e4c5089
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/EncryptedDigest.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_EncryptedDigest_H_
> +#define	_EncryptedDigest_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <OCTET_STRING.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* EncryptedDigest */
> +typedef OCTET_STRING_t	 EncryptedDigest_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_EncryptedDigest;
> +asn_struct_free_f EncryptedDigest_free;
> +asn_struct_print_f EncryptedDigest_print;
> +asn_constr_check_f EncryptedDigest_constraint;
> +ber_type_decoder_f EncryptedDigest_decode_ber;
> +der_type_encoder_f EncryptedDigest_encode_der;
> +xer_type_decoder_f EncryptedDigest_decode_xer;
> +xer_type_encoder_f EncryptedDigest_encode_xer;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _EncryptedDigest_H_ */
> +#include <asn_internal.h>
> diff --git
> a/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c
> b/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c new
> file mode 100644 index 000000000000..e48187af0036 --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.c
> @@ -0,0 +1,52 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "ExtendedCertificatesAndCertificates.h"
> +
> +static asn_TYPE_member_t
> asn_MBR_ExtendedCertificatesAndCertificates_1[] =3D {
> +	{ ATF_OPEN_TYPE | ATF_POINTER, 0, 0,
> +		-1 /* Ambiguous tag (ANY?) */,
> +		0,
> +		&asn_DEF_Certificate,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t
> asn_DEF_ExtendedCertificatesAndCertificates_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
> +};
> +static asn_SET_OF_specifics_t
> asn_SPC_ExtendedCertificatesAndCertificates_specs_1 =3D {
> +	sizeof(struct ExtendedCertificatesAndCertificates),
> +	offsetof(struct ExtendedCertificatesAndCertificates,
> _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +asn_TYPE_descriptor_t asn_DEF_ExtendedCertificatesAndCertificates =3D {
> +	"ExtendedCertificatesAndCertificates",
> +	"ExtendedCertificatesAndCertificates",
> +	SET_OF_free,
> +	SET_OF_print,
> +	SET_OF_constraint,
> +	SET_OF_decode_ber,
> +	SET_OF_encode_der,
> +	SET_OF_decode_xer,
> +	SET_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_ExtendedCertificatesAndCertificates_tags_1,
> +	sizeof(asn_DEF_ExtendedCertificatesAndCertificates_tags_1)
> +		/sizeof(asn_DEF_ExtendedCertificatesAndCertificates_tags_1[0]), /*
> 1 */
> +
> asn_DEF_ExtendedCertificatesAndCertificates_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_ExtendedCertificatesAndCertificates_tags_1)
> +		/sizeof(asn_DEF_ExtendedCertificatesAndCertificates_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_ExtendedCertificatesAndCertificates_1,
> +	1,	/* Single element */
> +
> &asn_SPC_ExtendedCertificatesAndCertificates_specs_1	/*
> Additional specs */ +}; +
> diff --git
> a/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h
> b/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h new
> file mode 100644 index 000000000000..dfe92ccbeddc --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ExtendedCertificatesAndCertificates.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_ExtendedCertificatesAndCertificates_H_
> +#define	_ExtendedCertificatesAndCertificates_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include "Certificate.h"
> +#include <asn_SET_OF.h>
> +#include <constr_SET_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* ExtendedCertificatesAndCertificates */
> +typedef struct ExtendedCertificatesAndCertificates {
> +	A_SET_OF(Certificate_t) list;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} ExtendedCertificatesAndCertificates_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t
> asn_DEF_ExtendedCertificatesAndCertificates; +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _ExtendedCertificatesAndCertificates_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/INTEGER.c
> b/libkmod/pkcs7/asn1c-gen/INTEGER.c new file mode 100644
> index 000000000000..eed82176b509
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/INTEGER.c
> @@ -0,0 +1,1025 @@
> +/*-
> + * Copyright (c) 2003-2014 Lev Walkin <vlm@lionet.info>.
> + * All rights reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <INTEGER.h>
> +#include <asn_codecs_prim.h>	/* Encoder and decoder of a
> primitive type */ +#include <errno.h>
> +
> +/*
> + * INTEGER basic type description.
> + */
> +static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
> +};
> +asn_TYPE_descriptor_t asn_DEF_INTEGER =3D {
> +	"INTEGER",
> +	"INTEGER",
> +	ASN__PRIMITIVE_TYPE_free,
> +	INTEGER_print,
> +	asn_generic_no_constraint,
> +	ber_decode_primitive,
> +	INTEGER_encode_der,
> +	INTEGER_decode_xer,
> +	INTEGER_encode_xer,
> +#ifdef	ASN_DISABLE_PER_SUPPORT
> +	0,
> +	0,
> +#else
> +	INTEGER_decode_uper,	/* Unaligned PER decoder */
> +	INTEGER_encode_uper,	/* Unaligned PER encoder */
> +#endif	/* ASN_DISABLE_PER_SUPPORT */
> +	0, /* Use generic outmost tag fetcher */
> +	asn_DEF_INTEGER_tags,
> +	sizeof(asn_DEF_INTEGER_tags) /
> sizeof(asn_DEF_INTEGER_tags[0]),
> +	asn_DEF_INTEGER_tags,	/* Same as above */
> +	sizeof(asn_DEF_INTEGER_tags) /
> sizeof(asn_DEF_INTEGER_tags[0]),
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> +/*
> + * Encode INTEGER type using DER.
> + */
> +asn_enc_rval_t
> +INTEGER_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
> +	int tag_mode, ber_tlv_tag_t tag,
> +	asn_app_consume_bytes_f *cb, void *app_key) {
> +	INTEGER_t *st =3D (INTEGER_t *)sptr;
> +
> +	ASN_DEBUG("%s %s as INTEGER (tm=3D%d)",
> +		cb?"Encoding":"Estimating", td->name, tag_mode);
> +
> +	/*
> +	 * Canonicalize integer in the buffer.
> +	 * (Remove too long sign extension, remove some first 0x00
> bytes)
> +	 */
> +	if(st->buf) {
> +		uint8_t *buf =3D st->buf;
> +		uint8_t *end1 =3D buf + st->size - 1;
> +		int shift;
> +
> +		/* Compute the number of superfluous leading bytes */
> +		for(; buf < end1; buf++) {
> +			/*
> +			 * If the contents octets of an integer
> value encoding
> +			 * consist of more than one octet, then the
> bits of the
> +			 * first octet and bit 8 of the second octet:
> +			 * a) shall not all be ones; and
> +			 * b) shall not all be zero.
> +			 */
> +			switch(*buf) {
> +			case 0x00: if((buf[1] & 0x80) =3D=3D 0)
> +					continue;
> +				break;
> +			case 0xff: if((buf[1] & 0x80))
> +					continue;
> +				break;
> +			}
> +			break;
> +		}
> +
> +		/* Remove leading superfluous bytes from the integer
> */
> +		shift =3D buf - st->buf;
> +		if(shift) {
> +			uint8_t *nb =3D st->buf;
> +			uint8_t *end;
> +
> +			st->size -=3D shift;	/* New size, minus
> bad bytes */
> +			end =3D nb + st->size;
> +
> +			for(; nb < end; nb++, buf++)
> +				*nb =3D *buf;
> +		}
> +
> +	} /* if(1) */
> +
> +	return der_encode_primitive(td, sptr, tag_mode, tag, cb,
> app_key); +}
> +
> +static const asn_INTEGER_enum_map_t
> *INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char
> *lstart, const char *lstop); + +/*
> + * INTEGER specific human-readable output.
> + */
> +static ssize_t
> +INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st,
> asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +	char scratch[32];	/* Enough for 64-bit integer */
> +	uint8_t *buf =3D st->buf;
> +	uint8_t *buf_end =3D st->buf + st->size;
> +	signed long value;
> +	ssize_t wrote =3D 0;
> +	char *p;
> +	int ret;
> +
> +	if(specs && specs->field_unsigned)
> +		ret =3D asn_INTEGER2ulong(st, (unsigned long *)&value);
> +	else
> +		ret =3D asn_INTEGER2long(st, &value);
> +
> +	/* Simple case: the integer size is small */
> +	if(ret =3D=3D 0) {
> +		const asn_INTEGER_enum_map_t *el;
> +		size_t scrsize;
> +		char *scr;
> +
> +		el =3D (value >=3D 0 || !specs || !specs->field_unsigned)
> +			? INTEGER_map_value2enum(specs, value) : 0;
> +		if(el) {
> +			scrsize =3D el->enum_len + 32;
> +			scr =3D (char *)alloca(scrsize);
> +			if(plainOrXER =3D=3D 0)
> +				ret =3D snprintf(scr, scrsize,
> +					"%ld (%s)", value,
> el->enum_name);
> +			else
> +				ret =3D snprintf(scr, scrsize,
> +					"<%s/>", el->enum_name);
> +		} else if(plainOrXER && specs &&
> specs->strict_enumeration) {
> +			ASN_DEBUG("ASN.1 forbids dealing with "
> +				"unknown value of ENUMERATED type");
> +			errno =3D EPERM;
> +			return -1;
> +		} else {
> +			scrsize =3D sizeof(scratch);
> +			scr =3D scratch;
> +			ret =3D snprintf(scr, scrsize,
> +				(specs && specs->field_unsigned)
> +				?"%lu":"%ld", value);
> +		}
> +		assert(ret > 0 && (size_t)ret < scrsize);
> +		return (cb(scr, ret, app_key) < 0) ? -1 : ret;
> +	} else if(plainOrXER && specs && specs->strict_enumeration) {
> +		/*
> +		 * Here and earlier, we cannot encode the ENUMERATED
> values
> +		 * if there is no corresponding identifier.
> +		 */
> +		ASN_DEBUG("ASN.1 forbids dealing with "
> +			"unknown value of ENUMERATED type");
> +		errno =3D EPERM;
> +		return -1;
> +	}
> +
> +	/* Output in the long xx:yy:zz... format */
> +	/* TODO: replace with generic algorithm (Knuth TAOCP Vol 2,
> 4.3.1) */
> +	for(p =3D scratch; buf < buf_end; buf++) {
> +		const char * const h2c =3D "0123456789ABCDEF";
> +		if((p - scratch) >=3D (ssize_t)(sizeof(scratch) - 4)) {
> +			/* Flush buffer */
> +			if(cb(scratch, p - scratch, app_key) < 0)
> +				return -1;
> +			wrote +=3D p - scratch;
> +			p =3D scratch;
> +		}
> +		*p++ =3D h2c[*buf >> 4];
> +		*p++ =3D h2c[*buf & 0x0F];
> +		*p++ =3D 0x3a;	/* ":" */
> +	}
> +	if(p !=3D scratch)
> +		p--;	/* Remove the last ":" */
> +
> +	wrote +=3D p - scratch;
> +	return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;
> +}
> +
> +/*
> + * INTEGER specific human-readable output.
> + */
> +int
> +INTEGER_print(asn_TYPE_descriptor_t *td, const void *sptr, int
> ilevel,
> +	asn_app_consume_bytes_f *cb, void *app_key) {
> +	const INTEGER_t *st =3D (const INTEGER_t *)sptr;
> +	ssize_t ret;
> +
> +	(void)td;
> +	(void)ilevel;
> +
> +	if(!st || !st->buf)
> +		ret =3D cb("<absent>", 8, app_key);
> +	else
> +		ret =3D INTEGER__dump(td, st, cb, app_key, 0);
> +
> +	return (ret < 0) ? -1 : 0;
> +}
> +
> +struct e2v_key {
> +	const char *start;
> +	const char *stop;
> +	const asn_INTEGER_enum_map_t *vemap;
> +	const unsigned int *evmap;
> +};
> +static int
> +INTEGER__compar_enum2value(const void *kp, const void *am) {
> +	const struct e2v_key *key =3D (const struct e2v_key *)kp;
> +	const asn_INTEGER_enum_map_t *el =3D (const
> asn_INTEGER_enum_map_t *)am;
> +	const char *ptr, *end, *name;
> +
> +	/* Remap the element (sort by different criterion) */
> +	el =3D key->vemap + key->evmap[el - key->vemap];
> +
> +	/* Compare strings */
> +	for(ptr =3D key->start, end =3D key->stop, name =3D el->enum_name;
> +			ptr < end; ptr++, name++) {
> +		if(*ptr !=3D *name)
> +			return *(const unsigned char *)ptr
> +				- *(const unsigned char *)name;
> +	}
> +	return name[0] ? -1 : 0;
> +}
> +
> +static const asn_INTEGER_enum_map_t *
> +INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char
> *lstart, const char *lstop) {
> +	const asn_INTEGER_enum_map_t *el_found;
> +	int count =3D specs ? specs->map_count : 0;
> +	struct e2v_key key;
> +	const char *lp;
> +
> +	if(!count) return NULL;
> +
> +	/* Guaranteed: assert(lstart < lstop); */
> +	/* Figure out the tag name */
> +	for(lstart++, lp =3D lstart; lp < lstop; lp++) {
> +		switch(*lp) {
> +		case 9: case 10: case 11: case 12: case 13: case
> 32: /* WSP */
> +		case 0x2f: /* '/' */ case 0x3e: /* '>' */
> +			break;
> +		default:
> +			continue;
> +		}
> +		break;
> +	}
> +	if(lp =3D=3D lstop) return NULL;	/* No tag found */
> +	lstop =3D lp;
> +
> +	key.start =3D lstart;
> +	key.stop =3D lstop;
> +	key.vemap =3D specs->value2enum;
> +	key.evmap =3D specs->enum2value;
> +	el_found =3D (asn_INTEGER_enum_map_t *)bsearch(&key,
> +		specs->value2enum, count,
> sizeof(specs->value2enum[0]),
> +		INTEGER__compar_enum2value);
> +	if(el_found) {
> +		/* Remap enum2value into value2enum */
> +		el_found =3D key.vemap + key.evmap[el_found -
> key.vemap];
> +	}
> +	return el_found;
> +}
> +
> +static int
> +INTEGER__compar_value2enum(const void *kp, const void *am) {
> +	long a =3D *(const long *)kp;
> +	const asn_INTEGER_enum_map_t *el =3D (const
> asn_INTEGER_enum_map_t *)am;
> +	long b =3D el->nat_value;
> +	if(a < b) return -1;
> +	else if(a =3D=3D b) return 0;
> +	else return 1;
> +}
> +
> +const asn_INTEGER_enum_map_t *
> +INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) {
> +	int count =3D specs ? specs->map_count : 0;
> +	if(!count) return 0;
> +	return (asn_INTEGER_enum_map_t *)bsearch(&value,
> specs->value2enum,
> +		count, sizeof(specs->value2enum[0]),
> +		INTEGER__compar_value2enum);
> +}
> +
> +static int
> +INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
> +	void *p =3D MALLOC(min_size + 1);
> +	if(p) {
> +		void *b =3D st->buf;
> +		st->size =3D 0;
> +		st->buf =3D p;
> +		FREEMEM(b);
> +		return 0;
> +	} else {
> +		return -1;
> +	}
> +}
> +
> +/*
> + * Decode the chunk of XML text encoding INTEGER.
> + */
> +static enum xer_pbd_rval
> +INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr,
> const void *chunk_buf, size_t chunk_size) {
> +	INTEGER_t *st =3D (INTEGER_t *)sptr;
> +	long dec_value;
> +	long hex_value =3D 0;
> +	const char *lp;
> +	const char *lstart =3D (const char *)chunk_buf;
> +	const char *lstop =3D lstart + chunk_size;
> +	enum {
> +		ST_LEADSPACE,
> +		ST_SKIPSPHEX,
> +		ST_WAITDIGITS,
> +		ST_DIGITS,
> +		ST_DIGITS_TRAILSPACE,
> +		ST_HEXDIGIT1,
> +		ST_HEXDIGIT2,
> +		ST_HEXDIGITS_TRAILSPACE,
> +		ST_HEXCOLON,
> +		ST_END_ENUM,
> +		ST_UNEXPECTED
> +	} state =3D ST_LEADSPACE;
> +	const char *dec_value_start =3D 0; /* INVARIANT: always !0 in
> ST_DIGITS */
> +	const char *dec_value_end =3D 0;
> +
> +	if(chunk_size)
> +		ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
> +			(long)chunk_size, *lstart, lstop[-1]);
> +
> +	if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
> +		return XPBD_SYSTEM_FAILURE;
> +
> +	/*
> +	 * We may have received a tag here. It will be processed
> inline.
> +	 * Use strtoul()-like code and serialize the result.
> +	 */
> +	for(lp =3D lstart; lp < lstop; lp++) {
> +		int lv =3D *lp;
> +		switch(lv) {
> +		case 0x09: case 0x0a: case 0x0d: case 0x20:
> +			switch(state) {
> +			case ST_LEADSPACE:
> +			case ST_DIGITS_TRAILSPACE:
> +			case ST_HEXDIGITS_TRAILSPACE:
> +			case ST_SKIPSPHEX:
> +				continue;
> +			case ST_DIGITS:
> +				dec_value_end =3D lp;
> +				state =3D ST_DIGITS_TRAILSPACE;
> +				continue;
> +			case ST_HEXCOLON:
> +				state =3D ST_HEXDIGITS_TRAILSPACE;
> +				continue;
> +			default:
> +				break;
> +			}
> +			break;
> +		case 0x2d:	/* '-' */
> +			if(state =3D=3D ST_LEADSPACE) {
> +				dec_value =3D 0;
> +				dec_value_start =3D lp;
> +				state =3D ST_WAITDIGITS;
> +				continue;
> +			}
> +			break;
> +		case 0x2b:	/* '+' */
> +			if(state =3D=3D ST_LEADSPACE) {
> +				dec_value =3D 0;
> +				dec_value_start =3D lp;
> +				state =3D ST_WAITDIGITS;
> +				continue;
> +			}
> +			break;
> +		case 0x30: case 0x31: case 0x32: case 0x33: case
> 0x34:
> +		case 0x35: case 0x36: case 0x37: case 0x38: case
> 0x39:
> +			switch(state) {
> +			case ST_DIGITS: continue;
> +			case ST_SKIPSPHEX:	/* Fall through */
> +			case ST_HEXDIGIT1:
> +				hex_value =3D (lv - 0x30) << 4;
> +				state =3D ST_HEXDIGIT2;
> +				continue;
> +			case ST_HEXDIGIT2:
> +				hex_value +=3D (lv - 0x30);
> +				state =3D ST_HEXCOLON;
> +				st->buf[st->size++] =3D
> (uint8_t)hex_value;
> +				continue;
> +			case ST_HEXCOLON:
> +				return XPBD_BROKEN_ENCODING;
> +			case ST_LEADSPACE:
> +				dec_value =3D 0;
> +				dec_value_start =3D lp;
> +				/* FALL THROUGH */
> +			case ST_WAITDIGITS:
> +				state =3D ST_DIGITS;
> +				continue;
> +			default:
> +				break;
> +			}
> +			break;
> +		case 0x3c:	/* '<', start of XML encoded
> enumeration */
> +			if(state =3D=3D ST_LEADSPACE) {
> +				const asn_INTEGER_enum_map_t *el;
> +				el =3D INTEGER_map_enum2value(
> +					(asn_INTEGER_specifics_t *)
> +					td->specifics, lstart,
> lstop);
> +				if(el) {
> +					ASN_DEBUG("Found \"%s\" =3D>
> %ld",
> +						el->enum_name,
> el->nat_value);
> +					dec_value =3D el->nat_value;
> +					state =3D ST_END_ENUM;
> +					lp =3D lstop - 1;
> +					continue;
> +				}
> +				ASN_DEBUG("Unknown identifier for
> INTEGER");
> +			}
> +			return XPBD_BROKEN_ENCODING;
> +		case 0x3a:	/* ':' */
> +			if(state =3D=3D ST_HEXCOLON) {
> +				/* This colon is expected */
> +				state =3D ST_HEXDIGIT1;
> +				continue;
> +			} else if(state =3D=3D ST_DIGITS) {
> +				/* The colon here means that we have
> +				 * decoded the first two hexadecimal
> +				 * places as a decimal value.
> +				 * Switch decoding mode. */
> +				ASN_DEBUG("INTEGER re-evaluate as
> hex form");
> +				state =3D ST_SKIPSPHEX;
> +				dec_value_start =3D 0;
> +				lp =3D lstart - 1;
> +				continue;
> +			} else {
> +				ASN_DEBUG("state %d at %ld", state,
> (long)(lp - lstart));
> +				break;
> +			}
> +		/* [A-Fa-f] */
> +		case 0x41:case 0x42:case 0x43:case 0x44:case
> 0x45:case 0x46:
> +		case 0x61:case 0x62:case 0x63:case 0x64:case
> 0x65:case 0x66:
> +			switch(state) {
> +			case ST_SKIPSPHEX:
> +			case ST_LEADSPACE: /* Fall through */
> +			case ST_HEXDIGIT1:
> +				hex_value =3D lv - ((lv < 0x61) ?
> 0x41 : 0x61);
> +				hex_value +=3D 10;
> +				hex_value <<=3D 4;
> +				state =3D ST_HEXDIGIT2;
> +				continue;
> +			case ST_HEXDIGIT2:
> +				hex_value +=3D lv - ((lv < 0x61) ?
> 0x41 : 0x61);
> +				hex_value +=3D 10;
> +				st->buf[st->size++] =3D
> (uint8_t)hex_value;
> +				state =3D ST_HEXCOLON;
> +				continue;
> +			case ST_DIGITS:
> +				ASN_DEBUG("INTEGER re-evaluate as
> hex form");
> +				state =3D ST_SKIPSPHEX;
> +				dec_value_start =3D 0;
> +				lp =3D lstart - 1;
> +				continue;
> +			default:
> +				break;
> +			}
> +			break;
> +		}
> +
> +		/* Found extra non-numeric stuff */
> +		ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at
> %ld",
> +			lv, (long)(lp - lstart));
> +		state =3D ST_UNEXPECTED;
> +		break;
> +	}
> +
> +	switch(state) {
> +	case ST_END_ENUM:
> +		/* Got a complete and valid enumeration encoded as a
> tag. */
> +		break;
> +	case ST_DIGITS:
> +		dec_value_end =3D lstop;
> +		/* FALL THROUGH */
> +	case ST_DIGITS_TRAILSPACE:
> +		/* The last symbol encountered was a digit. */
> +		switch(asn_strtol_lim(dec_value_start,
> &dec_value_end, &dec_value)) {
> +		case ASN_STRTOL_OK:
> +			break;
> +		case ASN_STRTOL_ERROR_RANGE:
> +			return XPBD_DECODER_LIMIT;
> +		case ASN_STRTOL_ERROR_INVAL:
> +		case ASN_STRTOL_EXPECT_MORE:
> +		case ASN_STRTOL_EXTRA_DATA:
> +			return XPBD_BROKEN_ENCODING;
> +		}
> +		break;
> +	case ST_HEXCOLON:
> +	case ST_HEXDIGITS_TRAILSPACE:
> +		st->buf[st->size] =3D 0;	/* Just in case
> termination */
> +		return XPBD_BODY_CONSUMED;
> +	case ST_HEXDIGIT1:
> +	case ST_HEXDIGIT2:
> +	case ST_SKIPSPHEX:
> +		return XPBD_BROKEN_ENCODING;
> +	case ST_LEADSPACE:
> +		/* Content not found */
> +		return XPBD_NOT_BODY_IGNORE;
> +	case ST_WAITDIGITS:
> +	case ST_UNEXPECTED:
> +		ASN_DEBUG("INTEGER: No useful digits (state %d)",
> state);
> +		return XPBD_BROKEN_ENCODING;	/* No digits */
> +	}
> +
> +	/*
> +	 * Convert the result of parsing of enumeration or a straight
> +	 * decimal value into a BER representation.
> +	 */
> +	if(asn_long2INTEGER(st, dec_value))
> +		return XPBD_SYSTEM_FAILURE;
> +
> +	return XPBD_BODY_CONSUMED;
> +}
> +
> +asn_dec_rval_t
> +INTEGER_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td, void **sptr, const char
> *opt_mname,
> +		const void *buf_ptr, size_t size) {
> +
> +	return xer_decode_primitive(opt_codec_ctx, td,
> +		sptr, sizeof(INTEGER_t), opt_mname,
> +		buf_ptr, size, INTEGER__xer_body_decode);
> +}
> +
> +asn_enc_rval_t
> +INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
> +	int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	const INTEGER_t *st =3D (const INTEGER_t *)sptr;
> +	asn_enc_rval_t er;
> +
> +	(void)ilevel;
> +	(void)flags;
> +=09
> +	if(!st || !st->buf)
> +		ASN__ENCODE_FAILED;
> +
> +	er.encoded =3D INTEGER__dump(td, st, cb, app_key, 1);
> +	if(er.encoded < 0) ASN__ENCODE_FAILED;
> +
> +	ASN__ENCODED_OK(er);
> +}
> +
> +#ifndef	ASN_DISABLE_PER_SUPPORT
> +
> +asn_dec_rval_t
> +INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +	asn_per_constraints_t *constraints, void **sptr,
> asn_per_data_t *pd) {
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +	asn_dec_rval_t rval =3D { RC_OK, 0 };
> +	INTEGER_t *st =3D (INTEGER_t *)*sptr;
> +	asn_per_constraint_t *ct;
> +	int repeat;
> +
> +	(void)opt_codec_ctx;
> +
> +	if(!st) {
> +		st =3D (INTEGER_t *)(*sptr =3D CALLOC(1, sizeof(*st)));
> +		if(!st) ASN__DECODE_FAILED;
> +	}
> +
> +	if(!constraints) constraints =3D td->per_constraints;
> +	ct =3D constraints ? &constraints->value : 0;
> +
> +	if(ct && ct->flags & APC_EXTENSIBLE) {
> +		int inext =3D per_get_few_bits(pd, 1);
> +		if(inext < 0) ASN__DECODE_STARVED;
> +		if(inext) ct =3D 0;
> +	}
> +
> +	FREEMEM(st->buf);
> +	st->buf =3D 0;
> +	st->size =3D 0;
> +	if(ct) {
> +		if(ct->flags & APC_SEMI_CONSTRAINED) {
> +			st->buf =3D (uint8_t *)CALLOC(1, 2);
> +			if(!st->buf) ASN__DECODE_FAILED;
> +			st->size =3D 1;
> +		} else if(ct->flags & APC_CONSTRAINED &&
> ct->range_bits >=3D 0) {
> +			size_t size =3D (ct->range_bits + 7) >> 3;
> +			st->buf =3D (uint8_t *)MALLOC(1 + size + 1);
> +			if(!st->buf) ASN__DECODE_FAILED;
> +			st->size =3D size;
> +		}
> +	}
> +
> +	/* X.691-2008/11, #13.2.2, constrained whole number */
> +	if(ct && ct->flags !=3D APC_UNCONSTRAINED) {
> +		/* #11.5.6 */
> +		ASN_DEBUG("Integer with range %d bits",
> ct->range_bits);
> +		if(ct->range_bits >=3D 0) {
> +			if((size_t)ct->range_bits > 8 *
> sizeof(unsigned long))
> +				ASN__DECODE_FAILED;
> +
> +			if(specs && specs->field_unsigned) {
> +				unsigned long uvalue;
> +
> if(uper_get_constrained_whole_number(pd,
> +					&uvalue, ct->range_bits))
> +					ASN__DECODE_STARVED;
> +				ASN_DEBUG("Got value %lu + low %ld",
> +					uvalue, ct->lower_bound);
> +				uvalue +=3D ct->lower_bound;
> +				if(asn_ulong2INTEGER(st, uvalue))
> +					ASN__DECODE_FAILED;
> +			} else {
> +				unsigned long svalue;
> +
> if(uper_get_constrained_whole_number(pd,
> +					&svalue, ct->range_bits))
> +					ASN__DECODE_STARVED;
> +				ASN_DEBUG("Got value %ld + low %ld",
> +					svalue, ct->lower_bound);
> +				svalue +=3D ct->lower_bound;
> +				if(asn_long2INTEGER(st, svalue))
> +					ASN__DECODE_FAILED;
> +			}
> +			return rval;
> +		}
> +	} else {
> +		ASN_DEBUG("Decoding unconstrained integer %s",
> td->name);
> +	}
> +
> +	/* X.691, #12.2.3, #12.2.4 */
> +	do {
> +		ssize_t len;
> +		void *p;
> +		int ret;
> +
> +		/* Get the PER length */
> +		len =3D uper_get_length(pd, -1, &repeat);
> +		if(len < 0) ASN__DECODE_STARVED;
> +
> +		p =3D REALLOC(st->buf, st->size + len + 1);
> +		if(!p) ASN__DECODE_FAILED;
> +		st->buf =3D (uint8_t *)p;
> +
> +		ret =3D per_get_many_bits(pd, &st->buf[st->size], 0, 8
> * len);
> +		if(ret < 0) ASN__DECODE_STARVED;
> +		st->size +=3D len;
> +	} while(repeat);
> +	st->buf[st->size] =3D 0;	/* JIC */
> +
> +	/* #12.2.3 */
> +	if(ct && ct->lower_bound) {
> +		/*
> +		 * TODO: replace by in-place arithmetics.
> +		 */
> +		long value;
> +		if(asn_INTEGER2long(st, &value))
> +			ASN__DECODE_FAILED;
> +		if(asn_long2INTEGER(st, value + ct->lower_bound))
> +			ASN__DECODE_FAILED;
> +	}
> +
> +	return rval;
> +}
> +
> +asn_enc_rval_t
> +INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
> +	asn_per_constraints_t *constraints, void *sptr,
> asn_per_outp_t *po) {
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +	asn_enc_rval_t er;
> +	INTEGER_t *st =3D (INTEGER_t *)sptr;
> +	const uint8_t *buf;
> +	const uint8_t *end;
> +	asn_per_constraint_t *ct;
> +	long value =3D 0;
> +	unsigned long v =3D 0;
> +
> +	if(!st || st->size =3D=3D 0) ASN__ENCODE_FAILED;
> +
> +	if(!constraints) constraints =3D td->per_constraints;
> +	ct =3D constraints ? &constraints->value : 0;
> +
> +	er.encoded =3D 0;
> +
> +	if(ct) {
> +		int inext =3D 0;
> +		if(specs && specs->field_unsigned) {
> +			unsigned long uval;
> +			if(asn_INTEGER2ulong(st, &uval))
> +				ASN__ENCODE_FAILED;
> +			/* Check proper range */
> +			if(ct->flags & APC_SEMI_CONSTRAINED) {
> +				if(uval < (unsigned
> long)ct->lower_bound)
> +					inext =3D 1;
> +			} else if(ct->range_bits >=3D 0) {
> +				if(uval < (unsigned
> long)ct->lower_bound
> +				|| uval > (unsigned
> long)ct->upper_bound)
> +					inext =3D 1;
> +			}
> +			ASN_DEBUG("Value %lu (%02x/%d) lb %lu ub %lu
> %s",
> +				uval, st->buf[0], st->size,
> +				ct->lower_bound, ct->upper_bound,
> +				inext ? "ext" : "fix");
> +			value =3D uval;
> +		} else {
> +			if(asn_INTEGER2long(st, &value))
> +				ASN__ENCODE_FAILED;
> +			/* Check proper range */
> +			if(ct->flags & APC_SEMI_CONSTRAINED) {
> +				if(value < ct->lower_bound)
> +					inext =3D 1;
> +			} else if(ct->range_bits >=3D 0) {
> +				if(value < ct->lower_bound
> +				|| value > ct->upper_bound)
> +					inext =3D 1;
> +			}
> +			ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld
> %s",
> +				value, st->buf[0], st->size,
> +				ct->lower_bound, ct->upper_bound,
> +				inext ? "ext" : "fix");
> +		}
> +		if(ct->flags & APC_EXTENSIBLE) {
> +			if(per_put_few_bits(po, inext, 1))
> +				ASN__ENCODE_FAILED;
> +			if(inext) ct =3D 0;
> +		} else if(inext) {
> +			ASN__ENCODE_FAILED;
> +		}
> +	}
> +
> +
> +	/* X.691-11/2008, #13.2.2, test if constrained whole number
> */
> +	if(ct && ct->range_bits >=3D 0) {
> +		/* #11.5.6 -> #11.3 */
> +		ASN_DEBUG("Encoding integer %ld (%lu) with range %d
> bits",
> +			value, value - ct->lower_bound,
> ct->range_bits);
> +		v =3D value - ct->lower_bound;
> +		if(uper_put_constrained_whole_number_u(po, v,
> ct->range_bits))
> +			ASN__ENCODE_FAILED;
> +		ASN__ENCODED_OK(er);
> +	}
> +
> +	if(ct && ct->lower_bound) {
> +		ASN_DEBUG("Adjust lower bound to %ld",
> ct->lower_bound);
> +		/* TODO: adjust lower bound */
> +		ASN__ENCODE_FAILED;
> +	}
> +
> +	for(buf =3D st->buf, end =3D st->buf + st->size; buf < end;) {
> +		ssize_t mayEncode =3D uper_put_length(po, end - buf);
> +		if(mayEncode < 0)
> +			ASN__ENCODE_FAILED;
> +		if(per_put_many_bits(po, buf, 8 * mayEncode))
> +			ASN__ENCODE_FAILED;
> +		buf +=3D mayEncode;
> +	}
> +
> +	ASN__ENCODED_OK(er);
> +}
> +
> +#endif	/* ASN_DISABLE_PER_SUPPORT */
> +
> +int
> +asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
> +	uint8_t *b, *end;
> +	size_t size;
> +	long l;
> +
> +	/* Sanity checking */
> +	if(!iptr || !iptr->buf || !lptr) {
> +		errno =3D EINVAL;
> +		return -1;
> +	}
> +
> +	/* Cache the begin/end of the buffer */
> +	b =3D iptr->buf;	/* Start of the INTEGER buffer */
> +	size =3D iptr->size;
> +	end =3D b + size;	/* Where to stop */
> +
> +	if(size > sizeof(long)) {
> +		uint8_t *end1 =3D end - 1;
> +		/*
> +		 * Slightly more advanced processing,
> +		 * able to >sizeof(long) bytes,
> +		 * when the actual value is small
> +		 * (0x0000000000abcdef would yield a fine 0x00abcdef)
> +		 */
> +		/* Skip out the insignificant leading bytes */
> +		for(; b < end1; b++) {
> +			switch(*b) {
> +			case 0x00: if((b[1] & 0x80) =3D=3D 0) continue;
> break;
> +			case 0xff: if((b[1] & 0x80) !=3D 0) continue;
> break;
> +			}
> +			break;
> +		}
> +
> +		size =3D end - b;
> +		if(size > sizeof(long)) {
> +			/* Still cannot fit the long */
> +			errno =3D ERANGE;
> +			return -1;
> +		}
> +	}
> +
> +	/* Shortcut processing of a corner case */
> +	if(end =3D=3D b) {
> +		*lptr =3D 0;
> +		return 0;
> +	}
> +
> +	/* Perform the sign initialization */
> +	/* Actually l =3D -(*b >> 7); gains nothing, yet unreadable! */
> +	if((*b >> 7)) l =3D -1; else l =3D 0;
> +
> +	/* Conversion engine */
> +	for(; b < end; b++)
> +		l =3D (l << 8) | *b;
> +
> +	*lptr =3D l;
> +	return 0;
> +}
> +
> +int
> +asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
> +	uint8_t *b, *end;
> +	unsigned long l;
> +	size_t size;
> +
> +	if(!iptr || !iptr->buf || !lptr) {
> +		errno =3D EINVAL;
> +		return -1;
> +	}
> +
> +	b =3D iptr->buf;
> +	size =3D iptr->size;
> +	end =3D b + size;
> +
> +	/* If all extra leading bytes are zeroes, ignore them */
> +	for(; size > sizeof(unsigned long); b++, size--) {
> +		if(*b) {
> +			/* Value won't fit unsigned long */
> +			errno =3D ERANGE;
> +			return -1;
> +		}
> +	}
> +
> +	/* Conversion engine */
> +	for(l =3D 0; b < end; b++)
> +		l =3D (l << 8) | *b;
> +
> +	*lptr =3D l;
> +	return 0;
> +}
> +
> +int
> +asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
> +	uint8_t *buf;
> +	uint8_t *end;
> +	uint8_t *b;
> +	int shr;
> +
> +	if(value <=3D LONG_MAX)
> +		return asn_long2INTEGER(st, value);
> +
> +	buf =3D (uint8_t *)MALLOC(1 + sizeof(value));
> +	if(!buf) return -1;
> +
> +	end =3D buf + (sizeof(value) + 1);
> +	buf[0] =3D 0;
> +	for(b =3D buf + 1, shr =3D (sizeof(long)-1)*8; b < end; shr -=3D
> 8, b++)
> +		*b =3D (uint8_t)(value >> shr);
> +
> +	if(st->buf) FREEMEM(st->buf);
> +	st->buf =3D buf;
> +	st->size =3D 1 + sizeof(value);
> +
> +	return 0;
> +}
> +
> +int
> +asn_long2INTEGER(INTEGER_t *st, long value) {
> +	uint8_t *buf, *bp;
> +	uint8_t *p;
> +	uint8_t *pstart;
> +	uint8_t *pend1;
> +	int littleEndian =3D 1;	/* Run-time detection */
> +	int add;
> +
> +	if(!st) {
> +		errno =3D EINVAL;
> +		return -1;
> +	}
> +
> +	buf =3D (uint8_t *)MALLOC(sizeof(value));
> +	if(!buf) return -1;
> +
> +	if(*(char *)&littleEndian) {
> +		pstart =3D (uint8_t *)&value + sizeof(value) - 1;
> +		pend1 =3D (uint8_t *)&value;
> +		add =3D -1;
> +	} else {
> +		pstart =3D (uint8_t *)&value;
> +		pend1 =3D pstart + sizeof(value) - 1;
> +		add =3D 1;
> +	}
> +
> +	/*
> +	 * If the contents octet consists of more than one octet,
> +	 * then bits of the first octet and bit 8 of the second
> octet:
> +	 * a) shall not all be ones; and
> +	 * b) shall not all be zero.
> +	 */
> +	for(p =3D pstart; p !=3D pend1; p +=3D add) {
> +		switch(*p) {
> +		case 0x00: if((*(p+add) & 0x80) =3D=3D 0)
> +				continue;
> +			break;
> +		case 0xff: if((*(p+add) & 0x80))
> +				continue;
> +			break;
> +		}
> +		break;
> +	}
> +	/* Copy the integer body */
> +	for(pstart =3D p, bp =3D buf, pend1 +=3D add; p !=3D pend1; p +=3D add)
> +		*bp++ =3D *p;
> +
> +	if(st->buf) FREEMEM(st->buf);
> +	st->buf =3D buf;
> +	st->size =3D bp - buf;
> +
> +	return 0;
> +}
> +
> +/*
> + * This function is going to be DEPRECATED soon.
> + */
> +enum asn_strtol_result_e
> +asn_strtol(const char *str, const char *end, long *lp) {
> +    const char *endp =3D end;
> +
> +    switch(asn_strtol_lim(str, &endp, lp)) {
> +    case ASN_STRTOL_ERROR_RANGE:
> +        return ASN_STRTOL_ERROR_RANGE;
> +    case ASN_STRTOL_ERROR_INVAL:
> +        return ASN_STRTOL_ERROR_INVAL;
> +    case ASN_STRTOL_EXPECT_MORE:
> +        return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
> +    case ASN_STRTOL_OK:
> +        return ASN_STRTOL_OK;
> +    case ASN_STRTOL_EXTRA_DATA:
> +        return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
> +    }
> +
> +    return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
> +}
> +
> +/*
> + * Parse the number in the given string until the given *end
> position,
> + * returning the position after the last parsed character back using
> the
> + * same (*end) pointer.
> + * WARNING: This behavior is different from the standard strtol(3).
> + */
> +enum asn_strtol_result_e
> +asn_strtol_lim(const char *str, const char **end, long *lp) {
> +	int sign =3D 1;
> +	long l;
> +
> +	const long upper_boundary =3D LONG_MAX / 10;
> +	long last_digit_max =3D LONG_MAX % 10;
> +
> +	if(str >=3D *end) return ASN_STRTOL_ERROR_INVAL;
> +
> +	switch(*str) {
> +	case '-':
> +		last_digit_max++;
> +		sign =3D -1;
> +		/* FALL THROUGH */
> +	case '+':
> +		str++;
> +		if(str >=3D *end) {
> +			*end =3D str;
> +			return ASN_STRTOL_EXPECT_MORE;
> +		}
> +	}
> +
> +	for(l =3D 0; str < (*end); str++) {
> +		switch(*str) {
> +		case 0x30: case 0x31: case 0x32: case 0x33: case
> 0x34:
> +		case 0x35: case 0x36: case 0x37: case 0x38: case
> 0x39: {
> +			int d =3D *str - '0';
> +			if(l < upper_boundary) {
> +				l =3D l * 10 + d;
> +			} else if(l =3D=3D upper_boundary) {
> +				if(d <=3D last_digit_max) {
> +					if(sign > 0) {
> +						l =3D l * 10 + d;
> +					} else {
> +						sign =3D 1;
> +						l =3D -l * 10 - d;
> +					}
> +				} else {
> +					*end =3D str;
> +					return
> ASN_STRTOL_ERROR_RANGE;
> +				}
> +			} else {
> +				*end =3D str;
> +				return ASN_STRTOL_ERROR_RANGE;
> +			}
> +		    }
> +		    continue;
> +		default:
> +		    *end =3D str;
> +		    *lp =3D sign * l;
> +		    return ASN_STRTOL_EXTRA_DATA;
> +		}
> +	}
> +
> +	*end =3D str;
> +	*lp =3D sign * l;
> +	return ASN_STRTOL_OK;
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/INTEGER.h
> b/libkmod/pkcs7/asn1c-gen/INTEGER.h new file mode 100644
> index 000000000000..9a8809707577
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/INTEGER.h
> @@ -0,0 +1,82 @@
> +/*-
> + * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	_INTEGER_H_
> +#define	_INTEGER_H_
> +
> +#include <asn_application.h>
> +#include <asn_codecs_prim.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
> +
> +extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
> +
> +/* Map with <tag> to integer value association */
> +typedef struct asn_INTEGER_enum_map_s {
> +	long		 nat_value;	/* associated native
> integer value */
> +	size_t		 enum_len;	/* strlen("tag") */
> +	const char	*enum_name;	/* "tag" */
> +} asn_INTEGER_enum_map_t;
> +
> +/* This type describes an enumeration for INTEGER and ENUMERATED
> types */ +typedef const struct asn_INTEGER_specifics_s {
> +	const asn_INTEGER_enum_map_t *value2enum;	/* N ->
> "tag"; sorted by N */
> +	const unsigned int *enum2value;		/* "tag" =3D>
> N; sorted by tag */
> +	int map_count;				/* Elements in
> either map */
> +	int extension;				/* This map is
> extensible */
> +	int strict_enumeration;			/*
> Enumeration set is fixed */
> +	int field_width;			/* Size of native
> integer */
> +	int field_unsigned;			/* Signed=3D0,
> unsigned=3D1 */ +} asn_INTEGER_specifics_t;
> +
> +asn_struct_print_f INTEGER_print;
> +ber_type_decoder_f INTEGER_decode_ber;
> +der_type_encoder_f INTEGER_encode_der;
> +xer_type_decoder_f INTEGER_decode_xer;
> +xer_type_encoder_f INTEGER_encode_xer;
> +per_type_decoder_f INTEGER_decode_uper;
> +per_type_encoder_f INTEGER_encode_uper;
> +
> +/***********************************
> + * Some handy conversion routines. *
> + ***********************************/
> +
> +/*
> + * Returns 0 if it was possible to convert, -1 otherwise.
> + * -1/EINVAL: Mandatory argument missing
> + * -1/ERANGE: Value encoded is out of range for long representation
> + * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
> + */
> +int asn_INTEGER2long(const INTEGER_t *i, long *l);
> +int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l);
> +int asn_long2INTEGER(INTEGER_t *i, long l);
> +int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l);
> +
> +/* A a reified version of strtol(3) with nicer error reporting. */
> +enum asn_strtol_result_e {
> +    ASN_STRTOL_ERROR_RANGE =3D -3,  /* Input outside of numeric range
> for long type */
> +    ASN_STRTOL_ERROR_INVAL =3D -2,  /* Invalid data encountered (e.g.,
> "+-") */
> +    ASN_STRTOL_EXPECT_MORE =3D -1,  /* More data expected (e.g. "+") */
> +    ASN_STRTOL_OK          =3D  0,  /* Conversion succeded, number
> ends at (*end) */
> +    ASN_STRTOL_EXTRA_DATA  =3D  1   /* Conversion succeded, but the
> string has extra stuff */ +};
> +enum asn_strtol_result_e asn_strtol_lim(const char *str, const char
> **end, long *l); +
> +/* The asn_strtol is going to be DEPRECATED soon */
> +enum asn_strtol_result_e asn_strtol(const char *str, const char
> *end, long *l); +
> +/*
> + * Convert the integer value into the corresponding enumeration map
> entry.
> + */
> +const asn_INTEGER_enum_map_t
> *INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value); +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _INTEGER_H_ */
> diff --git a/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c
> b/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c new file mode 100644
> index 000000000000..885de3cbc498
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.c
> @@ -0,0 +1,65 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "IssuerAndSerialNumber.h"
> +
> +static asn_TYPE_member_t asn_MBR_IssuerAndSerialNumber_1[] =3D {
> +	{ ATF_OPEN_TYPE | ATF_NOFLAGS, 0, offsetof(struct
> IssuerAndSerialNumber, issuer),
> +		-1 /* Ambiguous tag (ANY?) */,
> +		0,
> +		&asn_DEF_ANY,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"issuer"
> +		},
> +	{ ATF_OPEN_TYPE | ATF_NOFLAGS, 0, offsetof(struct
> IssuerAndSerialNumber, serialNumber),
> +		-1 /* Ambiguous tag (ANY?) */,
> +		0,
> +		&asn_DEF_ANY,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"serialNumber"
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_IssuerAndSerialNumber_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static asn_SEQUENCE_specifics_t
> asn_SPC_IssuerAndSerialNumber_specs_1 =3D {
> +	sizeof(struct IssuerAndSerialNumber),
> +	offsetof(struct IssuerAndSerialNumber, _asn_ctx),
> +	0,	/* No top level tags */
> +	0,	/* No tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_IssuerAndSerialNumber =3D {
> +	"IssuerAndSerialNumber",
> +	"IssuerAndSerialNumber",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_IssuerAndSerialNumber_tags_1,
> +	sizeof(asn_DEF_IssuerAndSerialNumber_tags_1)
> +		/sizeof(asn_DEF_IssuerAndSerialNumber_tags_1[0]), /*
> 1 */
> +	asn_DEF_IssuerAndSerialNumber_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_IssuerAndSerialNumber_tags_1)
> +		/sizeof(asn_DEF_IssuerAndSerialNumber_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_IssuerAndSerialNumber_1,
> +	2,	/* Elements count */
> +	&asn_SPC_IssuerAndSerialNumber_specs_1	/* Additional
> specs */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h
> b/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h new file mode 100644
> index 000000000000..477fd0ccbcef
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/IssuerAndSerialNumber.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_IssuerAndSerialNumber_H_
> +#define	_IssuerAndSerialNumber_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <ANY.h>
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* IssuerAndSerialNumber */
> +typedef struct IssuerAndSerialNumber {
> +	ANY_t	 issuer;
> +	ANY_t	 serialNumber;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} IssuerAndSerialNumber_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_IssuerAndSerialNumber;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _IssuerAndSerialNumber_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/Makefile.am.sample
> b/libkmod/pkcs7/asn1c-gen/Makefile.am.sample new file mode 100644
> index 000000000000..122279af6bbd
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Makefile.am.sample
> @@ -0,0 +1,150 @@
> +ASN_MODULE_SOURCES=3D	\
> +	PKCS7ContentInfo.c	\
> +	ContentType.c	\
> +	SignedData.c	\
> +	ContentInfo.c	\
> +	Data.c	\
> +	DigestAlgorithmIdentifiers.c	\
> +	DigestAlgorithmIdentifier.c	\
> +	ExtendedCertificatesAndCertificates.c	\
> +	Certificates.c	\
> +	CertificateRevocationLists.c	\
> +	CertificateList.c	\
> +	CRLSequence.c	\
> +	Certificate.c	\
> +	SignerInfos.c	\
> +	SignerInfo.c	\
> +	SignerIdentifier.c	\
> +	IssuerAndSerialNumber.c	\
> +	CertificateSerialNumber.c	\
> +	SubjectKeyIdentifier.c	\
> +	SetOfAuthenticatedAttribute.c	\
> +	Values.c	\
> +	AuthenticatedAttribute.c	\
> +	UnauthenticatedAttribute.c	\
> +	DigestEncryptionAlgorithmIdentifier.c	\
> +	EncryptedDigest.c	\
> +	Name.c	\
> +	RelativeDistinguishedName.c	\
> +	AttributeValueAssertion.c
> +
> +ASN_MODULE_HEADERS=3D	\
> +	PKCS7ContentInfo.h	\
> +	ContentType.h	\
> +	SignedData.h	\
> +	ContentInfo.h	\
> +	Data.h	\
> +	DigestAlgorithmIdentifiers.h	\
> +	DigestAlgorithmIdentifier.h	\
> +	ExtendedCertificatesAndCertificates.h	\
> +	Certificates.h	\
> +	CertificateRevocationLists.h	\
> +	CertificateList.h	\
> +	CRLSequence.h	\
> +	Certificate.h	\
> +	SignerInfos.h	\
> +	SignerInfo.h	\
> +	SignerIdentifier.h	\
> +	IssuerAndSerialNumber.h	\
> +	CertificateSerialNumber.h	\
> +	SubjectKeyIdentifier.h	\
> +	SetOfAuthenticatedAttribute.h	\
> +	Values.h	\
> +	AuthenticatedAttribute.h	\
> +	UnauthenticatedAttribute.h	\
> +	DigestEncryptionAlgorithmIdentifier.h	\
> +	EncryptedDigest.h	\
> +	Name.h	\
> +	RelativeDistinguishedName.h	\
> +	AttributeValueAssertion.h
> +
> +ASN_MODULE_HEADERS+=3DANY.h
> +ASN_MODULE_SOURCES+=3DANY.c
> +ASN_MODULE_HEADERS+=3DINTEGER.h
> +ASN_MODULE_HEADERS+=3DNativeEnumerated.h
> +ASN_MODULE_SOURCES+=3DINTEGER.c
> +ASN_MODULE_SOURCES+=3DNativeEnumerated.c
> +ASN_MODULE_HEADERS+=3DNativeInteger.h
> +ASN_MODULE_SOURCES+=3DNativeInteger.c
> +ASN_MODULE_HEADERS+=3DOBJECT_IDENTIFIER.h
> +ASN_MODULE_SOURCES+=3DOBJECT_IDENTIFIER.c
> +ASN_MODULE_HEADERS+=3Dasn_SEQUENCE_OF.h
> +ASN_MODULE_SOURCES+=3Dasn_SEQUENCE_OF.c
> +ASN_MODULE_HEADERS+=3Dasn_SET_OF.h
> +ASN_MODULE_SOURCES+=3Dasn_SET_OF.c
> +ASN_MODULE_HEADERS+=3Dconstr_CHOICE.h
> +ASN_MODULE_SOURCES+=3Dconstr_CHOICE.c
> +ASN_MODULE_HEADERS+=3Dconstr_SEQUENCE.h
> +ASN_MODULE_SOURCES+=3Dconstr_SEQUENCE.c
> +ASN_MODULE_HEADERS+=3Dconstr_SEQUENCE_OF.h
> +ASN_MODULE_SOURCES+=3Dconstr_SEQUENCE_OF.c
> +ASN_MODULE_HEADERS+=3Dconstr_SET_OF.h
> +ASN_MODULE_SOURCES+=3Dconstr_SET_OF.c
> +ASN_MODULE_HEADERS+=3Dasn_application.h
> +ASN_MODULE_HEADERS+=3Dasn_system.h
> +ASN_MODULE_HEADERS+=3Dasn_codecs.h
> +ASN_MODULE_HEADERS+=3Dasn_internal.h
> +ASN_MODULE_HEADERS+=3DOCTET_STRING.h
> +ASN_MODULE_SOURCES+=3DOCTET_STRING.c
> +ASN_MODULE_HEADERS+=3DBIT_STRING.h
> +ASN_MODULE_SOURCES+=3DBIT_STRING.c
> +ASN_MODULE_SOURCES+=3Dasn_codecs_prim.c
> +ASN_MODULE_HEADERS+=3Dasn_codecs_prim.h
> +ASN_MODULE_HEADERS+=3Dber_tlv_length.h
> +ASN_MODULE_SOURCES+=3Dber_tlv_length.c
> +ASN_MODULE_HEADERS+=3Dber_tlv_tag.h
> +ASN_MODULE_SOURCES+=3Dber_tlv_tag.c
> +ASN_MODULE_HEADERS+=3Dber_decoder.h
> +ASN_MODULE_SOURCES+=3Dber_decoder.c
> +ASN_MODULE_HEADERS+=3Dder_encoder.h
> +ASN_MODULE_SOURCES+=3Dder_encoder.c
> +ASN_MODULE_HEADERS+=3Dconstr_TYPE.h
> +ASN_MODULE_SOURCES+=3Dconstr_TYPE.c
> +ASN_MODULE_HEADERS+=3Dconstraints.h
> +ASN_MODULE_SOURCES+=3Dconstraints.c
> +ASN_MODULE_HEADERS+=3Dxer_support.h
> +ASN_MODULE_SOURCES+=3Dxer_support.c
> +ASN_MODULE_HEADERS+=3Dxer_decoder.h
> +ASN_MODULE_SOURCES+=3Dxer_decoder.c
> +ASN_MODULE_HEADERS+=3Dxer_encoder.h
> +ASN_MODULE_SOURCES+=3Dxer_encoder.c
> +ASN_MODULE_HEADERS+=3Dper_support.h
> +ASN_MODULE_SOURCES+=3Dper_support.c
> +ASN_MODULE_HEADERS+=3Dper_decoder.h
> +ASN_MODULE_SOURCES+=3Dper_decoder.c
> +ASN_MODULE_HEADERS+=3Dper_encoder.h
> +ASN_MODULE_SOURCES+=3Dper_encoder.c
> +ASN_MODULE_HEADERS+=3Dper_opentype.h
> +ASN_MODULE_SOURCES+=3Dper_opentype.c
> +ASN_CONVERTER_SOURCES+=3Dconverter-sample.c
> +
> +
> +lib_LTLIBRARIES=3Dlibsomething.la
> +libsomething_la_SOURCES=3D$(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
> +
> +# This file may be used as an input for make(3)
> +# Remove the lines below to convert it into a pure .am file
> +TARGET =3D progname
> +CFLAGS +=3D -I.
> +OBJS=3D${ASN_MODULE_SOURCES:.c=3D.o} ${ASN_CONVERTER_SOURCES:.c=3D.o}
> +
> +all: $(TARGET)
> +
> +$(TARGET): ${OBJS}
> +	$(CC) $(CFLAGS) -o $(TARGET) ${OBJS} $(LDFLAGS) $(LIBS)
> +
> +.SUFFIXES:
> +.SUFFIXES: .c .o
> +
> +.c.o:
> +	$(CC) $(CFLAGS) -o $@ -c $<
> +
> +clean:
> +	rm -f $(TARGET)
> +	rm -f $(OBJS)
> +
> +regen: regenerate-from-asn1-source
> +
> +regenerate-from-asn1-source:
> +	asn1c -fwide-types ../pkcs7.asn1
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/Name.c
> b/libkmod/pkcs7/asn1c-gen/Name.c new file mode 100644
> index 000000000000..917727f2a807
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Name.c
> @@ -0,0 +1,52 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "Name.h"
> +
> +static asn_TYPE_member_t asn_MBR_Name_1[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
> +		0,
> +		&asn_DEF_RelativeDistinguishedName,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_Name_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_Name_specs_1 =3D {
> +	sizeof(struct Name),
> +	offsetof(struct Name, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +asn_TYPE_descriptor_t asn_DEF_Name =3D {
> +	"Name",
> +	"Name",
> +	SEQUENCE_OF_free,
> +	SEQUENCE_OF_print,
> +	SEQUENCE_OF_constraint,
> +	SEQUENCE_OF_decode_ber,
> +	SEQUENCE_OF_encode_der,
> +	SEQUENCE_OF_decode_xer,
> +	SEQUENCE_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_Name_tags_1,
> +	sizeof(asn_DEF_Name_tags_1)
> +		/sizeof(asn_DEF_Name_tags_1[0]), /* 1 */
> +	asn_DEF_Name_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_Name_tags_1)
> +		/sizeof(asn_DEF_Name_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_Name_1,
> +	1,	/* Single element */
> +	&asn_SPC_Name_specs_1	/* Additional specs */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/Name.h
> b/libkmod/pkcs7/asn1c-gen/Name.h new file mode 100644
> index 000000000000..fcb146344087
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Name.h
> @@ -0,0 +1,44 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_Name_H_
> +#define	_Name_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <asn_SEQUENCE_OF.h>
> +#include <constr_SEQUENCE_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Forward declarations */
> +struct RelativeDistinguishedName;
> +
> +/* Name */
> +typedef struct Name {
> +	A_SEQUENCE_OF(struct RelativeDistinguishedName) list;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} Name_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_Name;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +/* Referred external types */
> +#include "RelativeDistinguishedName.h"
> +
> +#endif	/* _Name_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/NativeEnumerated.c
> b/libkmod/pkcs7/asn1c-gen/NativeEnumerated.c new file mode 100644
> index 000000000000..78366af31840
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/NativeEnumerated.c
> @@ -0,0 +1,207 @@
> +/*-
> + * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +/*
> + * Read the NativeInteger.h for the explanation wrt. differences
> between
> + * INTEGER and NativeInteger.
> + * Basically, both are decoders and encoders of ASN.1 INTEGER type,
> but this
> + * implementation deals with the standard (machine-specific)
> representation
> + * of them instead of using the platform-independent buffer.
> + */
> +#include <asn_internal.h>
> +#include <NativeEnumerated.h>
> +
> +/*
> + * NativeEnumerated basic type description.
> + */
> +static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
> +};
> +asn_TYPE_descriptor_t asn_DEF_NativeEnumerated =3D {
> +	"ENUMERATED",			/* The ASN.1 type is
> still ENUMERATED */
> +	"ENUMERATED",
> +	NativeInteger_free,
> +	NativeInteger_print,
> +	asn_generic_no_constraint,
> +	NativeInteger_decode_ber,
> +	NativeInteger_encode_der,
> +	NativeInteger_decode_xer,
> +	NativeEnumerated_encode_xer,
> +	NativeEnumerated_decode_uper,
> +	NativeEnumerated_encode_uper,
> +	0, /* Use generic outmost tag fetcher */
> +	asn_DEF_NativeEnumerated_tags,
> +	sizeof(asn_DEF_NativeEnumerated_tags) /
> sizeof(asn_DEF_NativeEnumerated_tags[0]),
> +	asn_DEF_NativeEnumerated_tags,	/* Same as above */
> +	sizeof(asn_DEF_NativeEnumerated_tags) /
> sizeof(asn_DEF_NativeEnumerated_tags[0]),
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> +asn_enc_rval_t
> +NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
> +        int ilevel, enum xer_encoder_flags_e flags,
> +                asn_app_consume_bytes_f *cb, void *app_key) {
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +        asn_enc_rval_t er;
> +        const long *native =3D (const long *)sptr;
> +	const asn_INTEGER_enum_map_t *el;
> +
> +        (void)ilevel;
> +        (void)flags;
> +
> +        if(!native) ASN__ENCODE_FAILED;
> +
> +	el =3D INTEGER_map_value2enum(specs, *native);
> +	if(el) {
> +		size_t srcsize =3D el->enum_len + 5;
> +		char *src =3D (char *)alloca(srcsize);
> +
> +		er.encoded =3D snprintf(src, srcsize, "<%s/>",
> el->enum_name);
> +		assert(er.encoded > 0 && (size_t)er.encoded <
> srcsize);
> +		if(cb(src, er.encoded, app_key) < 0)
> ASN__ENCODE_FAILED;
> +		ASN__ENCODED_OK(er);
> +	} else {
> +		ASN_DEBUG("ASN.1 forbids dealing with "
> +			"unknown value of ENUMERATED type");
> +		ASN__ENCODE_FAILED;
> +	}
> +}
> +
> +asn_dec_rval_t
> +NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td, asn_per_constraints_t
> *constraints,
> +	void **sptr, asn_per_data_t *pd) {
> +	asn_INTEGER_specifics_t *specs =3D (asn_INTEGER_specifics_t
> *)td->specifics;
> +	asn_dec_rval_t rval =3D { RC_OK, 0 };
> +	long *native =3D (long *)*sptr;
> +	asn_per_constraint_t *ct;
> +	long value;
> +
> +	(void)opt_codec_ctx;
> +
> +	if(constraints) ct =3D &constraints->value;
> +	else if(td->per_constraints) ct =3D
> &td->per_constraints->value;
> +	else ASN__DECODE_FAILED;	/* Mandatory! */
> +	if(!specs) ASN__DECODE_FAILED;
> +
> +	if(!native) {
> +		native =3D (long *)(*sptr =3D CALLOC(1,
> sizeof(*native)));
> +		if(!native) ASN__DECODE_FAILED;
> +	}
> +
> +	ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
> +
> +	if(ct->flags & APC_EXTENSIBLE) {
> +		int inext =3D per_get_few_bits(pd, 1);
> +		if(inext < 0) ASN__DECODE_STARVED;
> +		if(inext) ct =3D 0;
> +	}
> +
> +	if(ct && ct->range_bits >=3D 0) {
> +		value =3D per_get_few_bits(pd, ct->range_bits);
> +		if(value < 0) ASN__DECODE_STARVED;
> +		if(value >=3D (specs->extension
> +			? specs->extension - 1 : specs->map_count))
> +			ASN__DECODE_FAILED;
> +	} else {
> +		if(!specs->extension)
> +			ASN__DECODE_FAILED;
> +		/*
> +		 * X.691, #10.6: normally small non-negative whole
> number;
> +		 */
> +		value =3D uper_get_nsnnwn(pd);
> +		if(value < 0) ASN__DECODE_STARVED;
> +		value +=3D specs->extension - 1;
> +		if(value >=3D specs->map_count)
> +			ASN__DECODE_FAILED;
> +	}
> +
> +	*native =3D specs->value2enum[value].nat_value;
> +	ASN_DEBUG("Decoded %s =3D %ld", td->name, *native);
> +
> +	return rval;
> +}
> +
> +static int
> +NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
> +	const asn_INTEGER_enum_map_t *a =3D ap;
> +	const asn_INTEGER_enum_map_t *b =3D bp;
> +	if(a->nat_value =3D=3D b->nat_value)
> +		return 0;
> +	if(a->nat_value < b->nat_value)
> +		return -1;
> +	return 1;
> +}
> +
> +asn_enc_rval_t
> +NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
> +	asn_per_constraints_t *constraints, void *sptr,
> asn_per_outp_t *po) {
> +	asn_INTEGER_specifics_t *specs =3D (asn_INTEGER_specifics_t
> *)td->specifics;
> +	asn_enc_rval_t er;
> +	long native, value;
> +	asn_per_constraint_t *ct;
> +	int inext =3D 0;
> +	asn_INTEGER_enum_map_t key;
> +	const asn_INTEGER_enum_map_t *kf;
> +
> +	if(!sptr) ASN__ENCODE_FAILED;
> +	if(!specs) ASN__ENCODE_FAILED;
> +
> +	if(constraints) ct =3D &constraints->value;
> +	else if(td->per_constraints) ct =3D
> &td->per_constraints->value;
> +	else ASN__ENCODE_FAILED;	/* Mandatory! */
> +
> +	ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
> +
> +	er.encoded =3D 0;
> +
> +	native =3D *(long *)sptr;
> +	if(native < 0) ASN__ENCODE_FAILED;
> +
> +	key.nat_value =3D native;
> +	kf =3D bsearch(&key, specs->value2enum, specs->map_count,
> +		sizeof(key), NativeEnumerated__compar_value2enum);
> +	if(!kf) {
> +		ASN_DEBUG("No element corresponds to %ld", native);
> +		ASN__ENCODE_FAILED;
> +	}
> +	value =3D kf - specs->value2enum;
> +
> +	if(ct->range_bits >=3D 0) {
> +		int cmpWith =3D specs->extension
> +				? specs->extension - 1 :
> specs->map_count;
> +		if(value >=3D cmpWith)
> +			inext =3D 1;
> +	}
> +	if(ct->flags & APC_EXTENSIBLE) {
> +		if(per_put_few_bits(po, inext, 1))
> +			ASN__ENCODE_FAILED;
> +		if(inext) ct =3D 0;
> +	} else if(inext) {
> +		ASN__ENCODE_FAILED;
> +	}
> +
> +	if(ct && ct->range_bits >=3D 0) {
> +		if(per_put_few_bits(po, value, ct->range_bits))
> +			ASN__ENCODE_FAILED;
> +		ASN__ENCODED_OK(er);
> +	}
> +
> +	if(!specs->extension)
> +		ASN__ENCODE_FAILED;
> +
> +	/*
> +	 * X.691, #10.6: normally small non-negative whole number;
> +	 */
> +	ASN_DEBUG("value =3D %ld, ext =3D %d, inext =3D %d, res =3D %ld",
> +		value, specs->extension, inext,
> +		value - (inext ? (specs->extension - 1) : 0));
> +	if(uper_put_nsnnwn(po, value - (inext ? (specs->extension -
> 1) : 0)))
> +		ASN__ENCODE_FAILED;
> +
> +	ASN__ENCODED_OK(er);
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/NativeEnumerated.h
> b/libkmod/pkcs7/asn1c-gen/NativeEnumerated.h new file mode 100644
> index 000000000000..c59bb1ba9438
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/NativeEnumerated.h
> @@ -0,0 +1,32 @@
> +/*-
> + * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
> + * All rights reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +/*
> + * This type differs from the standard ENUMERATED in that it is
> modelled using
> + * the fixed machine type (long, int, short), so it can hold only
> values of
> + * limited length. There is no type (i.e., NativeEnumerated_t, any
> integer type
> + * will do).
> + * This type may be used when integer range is limited by subtype
> constraints.
> + */
> +#ifndef	_NativeEnumerated_H_
> +#define	_NativeEnumerated_H_
> +
> +#include <NativeInteger.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
> +
> +xer_type_encoder_f NativeEnumerated_encode_xer;
> +per_type_decoder_f NativeEnumerated_decode_uper;
> +per_type_encoder_f NativeEnumerated_encode_uper;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _NativeEnumerated_H_ */
> diff --git a/libkmod/pkcs7/asn1c-gen/NativeInteger.c
> b/libkmod/pkcs7/asn1c-gen/NativeInteger.c new file mode 100644
> index 000000000000..e8ce6d2c33c1
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/NativeInteger.c
> @@ -0,0 +1,332 @@
> +/*-
> + * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
> + * All rights reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +/*
> + * Read the NativeInteger.h for the explanation wrt. differences
> between
> + * INTEGER and NativeInteger.
> + * Basically, both are decoders and encoders of ASN.1 INTEGER type,
> but this
> + * implementation deals with the standard (machine-specific)
> representation
> + * of them instead of using the platform-independent buffer.
> + */
> +#include <asn_internal.h>
> +#include <NativeInteger.h>
> +
> +/*
> + * NativeInteger basic type description.
> + */
> +static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
> +};
> +asn_TYPE_descriptor_t asn_DEF_NativeInteger =3D {
> +	"INTEGER",			/* The ASN.1 type is still
> INTEGER */
> +	"INTEGER",
> +	NativeInteger_free,
> +	NativeInteger_print,
> +	asn_generic_no_constraint,
> +	NativeInteger_decode_ber,
> +	NativeInteger_encode_der,
> +	NativeInteger_decode_xer,
> +	NativeInteger_encode_xer,
> +	NativeInteger_decode_uper,	/* Unaligned PER decoder */
> +	NativeInteger_encode_uper,	/* Unaligned PER encoder */
> +	0, /* Use generic outmost tag fetcher */
> +	asn_DEF_NativeInteger_tags,
> +	sizeof(asn_DEF_NativeInteger_tags) /
> sizeof(asn_DEF_NativeInteger_tags[0]),
> +	asn_DEF_NativeInteger_tags,	/* Same as above */
> +	sizeof(asn_DEF_NativeInteger_tags) /
> sizeof(asn_DEF_NativeInteger_tags[0]),
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> +/*
> + * Decode INTEGER type.
> + */
> +asn_dec_rval_t
> +NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td,
> +	void **nint_ptr, const void *buf_ptr, size_t size, int
> tag_mode) {
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +	long *native =3D (long *)*nint_ptr;
> +	asn_dec_rval_t rval;
> +	ber_tlv_len_t length;
> +
> +	/*
> +	 * If the structure is not there, allocate it.
> +	 */
> +	if(native =3D=3D NULL) {
> +		native =3D (long *)(*nint_ptr =3D CALLOC(1,
> sizeof(*native)));
> +		if(native =3D=3D NULL) {
> +			rval.code =3D RC_FAIL;
> +			rval.consumed =3D 0;
> +			return rval;
> +		}
> +	}
> +
> +	ASN_DEBUG("Decoding %s as INTEGER (tm=3D%d)",
> +		td->name, tag_mode);
> +
> +	/*
> +	 * Check tags.
> +	 */
> +	rval =3D ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
> +			tag_mode, 0, &length, 0);
> +	if(rval.code !=3D RC_OK)
> +		return rval;
> +
> +	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
> +
> +	/*
> +	 * Make sure we have this length.
> +	 */
> +	buf_ptr =3D ((const char *)buf_ptr) + rval.consumed;
> +	size -=3D rval.consumed;
> +	if(length > (ber_tlv_len_t)size) {
> +		rval.code =3D RC_WMORE;
> +		rval.consumed =3D 0;
> +		return rval;
> +	}
> +
> +	/*
> +	 * ASN.1 encoded INTEGER: buf_ptr, length
> +	 * Fill the native, at the same time checking for overflow.
> +	 * If overflow occured, return with RC_FAIL.
> +	 */
> +	{
> +		INTEGER_t tmp;
> +		union {
> +			const void *constbuf;
> +			void *nonconstbuf;
> +		} unconst_buf;
> +		long l;
> +
> +		unconst_buf.constbuf =3D buf_ptr;
> +		tmp.buf =3D (uint8_t *)unconst_buf.nonconstbuf;
> +		tmp.size =3D length;
> +
> +		if((specs&&specs->field_unsigned)
> +			? asn_INTEGER2ulong(&tmp, (unsigned long
> *)&l) /* sic */
> +			: asn_INTEGER2long(&tmp, &l)) {
> +			rval.code =3D RC_FAIL;
> +			rval.consumed =3D 0;
> +			return rval;
> +		}
> +
> +		*native =3D l;
> +	}
> +
> +	rval.code =3D RC_OK;
> +	rval.consumed +=3D length;
> +
> +	ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
> +		(long)rval.consumed, (long)length, td->name,
> (long)*native); +
> +	return rval;
> +}
> +
> +/*
> + * Encode the NativeInteger using the standard INTEGER type DER
> encoder.
> + */
> +asn_enc_rval_t
> +NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr,
> +	int tag_mode, ber_tlv_tag_t tag,
> +	asn_app_consume_bytes_f *cb, void *app_key) {
> +	unsigned long native =3D *(unsigned long *)ptr;	/*
> Disable sign ext. */
> +	asn_enc_rval_t erval;
> +	INTEGER_t tmp;
> +
> +#ifdef	WORDS_BIGENDIAN		/* Opportunistic
> optimization */ +
> +	tmp.buf =3D (uint8_t *)&native;
> +	tmp.size =3D sizeof(native);
> +
> +#else	/* Works even if WORDS_BIGENDIAN is not set where
> should've been */
> +	uint8_t buf[sizeof(native)];
> +	uint8_t *p;
> +
> +	/* Prepare a fake INTEGER */
> +	for(p =3D buf + sizeof(buf) - 1; p >=3D buf; p--, native >>=3D 8)
> +		*p =3D (uint8_t)native;
> +
> +	tmp.buf =3D buf;
> +	tmp.size =3D sizeof(buf);
> +#endif	/* WORDS_BIGENDIAN */
> +=09
> +	/* Encode fake INTEGER */
> +	erval =3D INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb,
> app_key);
> +	if(erval.encoded =3D=3D -1) {
> +		assert(erval.structure_ptr =3D=3D &tmp);
> +		erval.structure_ptr =3D ptr;
> +	}
> +	return erval;
> +}
> +
> +/*
> + * Decode the chunk of XML text encoding INTEGER.
> + */
> +asn_dec_rval_t
> +NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td, void **sptr, const char
> *opt_mname,
> +		const void *buf_ptr, size_t size) {
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +	asn_dec_rval_t rval;
> +	INTEGER_t st;
> +	void *st_ptr =3D (void *)&st;
> +	long *native =3D (long *)*sptr;
> +
> +	if(!native) {
> +		native =3D (long *)(*sptr =3D CALLOC(1,
> sizeof(*native)));
> +		if(!native) ASN__DECODE_FAILED;
> +	}
> +
> +	memset(&st, 0, sizeof(st));
> +	rval =3D INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr,=20
> +		opt_mname, buf_ptr, size);
> +	if(rval.code =3D=3D RC_OK) {
> +		long l;
> +		if((specs&&specs->field_unsigned)
> +			? asn_INTEGER2ulong(&st, (unsigned long
> *)&l) /* sic */
> +			: asn_INTEGER2long(&st, &l)) {
> +			rval.code =3D RC_FAIL;
> +			rval.consumed =3D 0;
> +		} else {
> +			*native =3D l;
> +		}
> +	} else {
> +		/*
> +		 * Cannot restart from the middle;
> +		 * there is no place to save state in the native
> type.
> +		 * Request a continuation from the very beginning.
> +		 */
> +		rval.consumed =3D 0;
> +	}
> +	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
> +	return rval;
> +}
> +
> +
> +asn_enc_rval_t
> +NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
> +	int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +	char scratch[32];	/* Enough for 64-bit int */
> +	asn_enc_rval_t er;
> +	const long *native =3D (const long *)sptr;
> +
> +	(void)ilevel;
> +	(void)flags;
> +
> +	if(!native) ASN__ENCODE_FAILED;
> +
> +	er.encoded =3D snprintf(scratch, sizeof(scratch),
> +			(specs && specs->field_unsigned)
> +			? "%lu" : "%ld", *native);
> +	if(er.encoded <=3D 0 || (size_t)er.encoded >=3D sizeof(scratch)
> +		|| cb(scratch, er.encoded, app_key) < 0)
> +		ASN__ENCODE_FAILED;
> +
> +	ASN__ENCODED_OK(er);
> +}
> +
> +asn_dec_rval_t
> +NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td,
> +	asn_per_constraints_t *constraints, void **sptr,
> asn_per_data_t *pd) { +
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +	asn_dec_rval_t rval;
> +	long *native =3D (long *)*sptr;
> +	INTEGER_t tmpint;
> +	void *tmpintptr =3D &tmpint;
> +
> +	(void)opt_codec_ctx;
> +	ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
> +
> +	if(!native) {
> +		native =3D (long *)(*sptr =3D CALLOC(1,
> sizeof(*native)));
> +		if(!native) ASN__DECODE_FAILED;
> +	}
> +
> +	memset(&tmpint, 0, sizeof tmpint);
> +	rval =3D INTEGER_decode_uper(opt_codec_ctx, td, constraints,
> +				   &tmpintptr, pd);
> +	if(rval.code =3D=3D RC_OK) {
> +		if((specs&&specs->field_unsigned)
> +			? asn_INTEGER2ulong(&tmpint, (unsigned long
> *)native)
> +			: asn_INTEGER2long(&tmpint, native))
> +			rval.code =3D RC_FAIL;
> +		else
> +			ASN_DEBUG("NativeInteger %s got value %ld",
> +				td->name, *native);
> +	}
> +	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
> +
> +	return rval;
> +}
> +
> +asn_enc_rval_t
> +NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
> +	asn_per_constraints_t *constraints, void *sptr,
> asn_per_outp_t *po) {
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +	asn_enc_rval_t er;
> +	long native;
> +	INTEGER_t tmpint;
> +
> +	if(!sptr) ASN__ENCODE_FAILED;
> +
> +	native =3D *(long *)sptr;
> +
> +	ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name,
> native); +
> +	memset(&tmpint, 0, sizeof(tmpint));
> +	if((specs&&specs->field_unsigned)
> +		? asn_ulong2INTEGER(&tmpint, native)
> +		: asn_long2INTEGER(&tmpint, native))
> +		ASN__ENCODE_FAILED;
> +	er =3D INTEGER_encode_uper(td, constraints, &tmpint, po);
> +	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
> +	return er;
> +}
> +
> +/*
> + * INTEGER specific human-readable output.
> + */
> +int
> +NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int
> ilevel,
> +	asn_app_consume_bytes_f *cb, void *app_key) {
> +	asn_INTEGER_specifics_t *specs=3D(asn_INTEGER_specifics_t
> *)td->specifics;
> +	const long *native =3D (const long *)sptr;
> +	char scratch[32];	/* Enough for 64-bit int */
> +	int ret;
> +
> +	(void)td;	/* Unused argument */
> +	(void)ilevel;	/* Unused argument */
> +
> +	if(native) {
> +		ret =3D snprintf(scratch, sizeof(scratch),
> +			(specs && specs->field_unsigned)
> +			? "%lu" : "%ld", *native);
> +		assert(ret > 0 && (size_t)ret < sizeof(scratch));
> +		return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
> +	} else {
> +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
> +	}
> +}
> +
> +void
> +NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int
> contents_only) { +
> +	if(!td || !ptr)
> +		return;
> +
> +	ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
> +		td->name, contents_only, ptr);
> +
> +	if(!contents_only) {
> +		FREEMEM(ptr);
> +	}
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/NativeInteger.h
> b/libkmod/pkcs7/asn1c-gen/NativeInteger.h new file mode 100644
> index 000000000000..4e63a8355d12
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/NativeInteger.h
> @@ -0,0 +1,37 @@
> +/*-
> + * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +/*
> + * This type differs from the standard INTEGER in that it is
> modelled using
> + * the fixed machine type (long, int, short), so it can hold only
> values of
> + * limited length. There is no type (i.e., NativeInteger_t, any
> integer type
> + * will do).
> + * This type may be used when integer range is limited by subtype
> constraints.
> + */
> +#ifndef	_NativeInteger_H_
> +#define	_NativeInteger_H_
> +
> +#include <asn_application.h>
> +#include <INTEGER.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +extern asn_TYPE_descriptor_t asn_DEF_NativeInteger;
> +
> +asn_struct_free_f  NativeInteger_free;
> +asn_struct_print_f NativeInteger_print;
> +ber_type_decoder_f NativeInteger_decode_ber;
> +der_type_encoder_f NativeInteger_encode_der;
> +xer_type_decoder_f NativeInteger_decode_xer;
> +xer_type_encoder_f NativeInteger_encode_xer;
> +per_type_decoder_f NativeInteger_decode_uper;
> +per_type_encoder_f NativeInteger_encode_uper;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _NativeInteger_H_ */
> diff --git a/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c
> b/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c new file mode 100644
> index 000000000000..d0f8b3117121
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.c
> @@ -0,0 +1,764 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <INTEGER.h>
> +#include <OBJECT_IDENTIFIER.h>
> +#include <OCTET_STRING.h>
> +#include <limits.h>	/* for CHAR_BIT */
> +#include <errno.h>
> +
> +/*
> + * OBJECT IDENTIFIER basic type description.
> + */
> +static const ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (6 << 2))
> +};
> +asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER =3D {
> +	"OBJECT IDENTIFIER",
> +	"OBJECT_IDENTIFIER",
> +	ASN__PRIMITIVE_TYPE_free,
> +	OBJECT_IDENTIFIER_print,
> +	OBJECT_IDENTIFIER_constraint,
> +	ber_decode_primitive,
> +	der_encode_primitive,
> +	OBJECT_IDENTIFIER_decode_xer,
> +	OBJECT_IDENTIFIER_encode_xer,
> +	OCTET_STRING_decode_uper,
> +	OCTET_STRING_encode_uper,
> +	0, /* Use generic outmost tag fetcher */
> +	asn_DEF_OBJECT_IDENTIFIER_tags,
> +	sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
> +	    / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
> +	asn_DEF_OBJECT_IDENTIFIER_tags,	/* Same as above */
> +	sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
> +	    / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> +
> +int
> +OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void
> *sptr,
> +		asn_app_constraint_failed_f *ctfailcb, void
> *app_key) {
> +	const OBJECT_IDENTIFIER_t *st =3D (const OBJECT_IDENTIFIER_t
> *)sptr; +
> +	if(st && st->buf) {
> +		if(st->size < 1) {
> +			ASN__CTFAIL(app_key, td, sptr,
> +				"%s: at least one numerical value "
> +				"expected (%s:%d)",
> +				td->name, __FILE__, __LINE__);
> +			return -1;
> +		}
> +	} else {
> +		ASN__CTFAIL(app_key, td, sptr,
> +			"%s: value not given (%s:%d)",
> +			td->name, __FILE__, __LINE__);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +
> +int
> +OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned int
> arclen, signed int add, void *rvbufp, unsigned int rvsize) {
> +	unsigned LE GCC_NOTUSED =3D 1; /* Little endian (x86) */
> +	const uint8_t *arcend =3D arcbuf + arclen;	/* End of
> arc */
> +	unsigned int cache =3D 0;	/* No more than 14
> significant bits */
> +	unsigned char *rvbuf =3D (unsigned char *)rvbufp;
> +	unsigned char *rvstart =3D rvbuf;	/* Original start of
> the value buffer */
> +	int inc;	/* Return value growth direction */
> +
> +	rvsize *=3D CHAR_BIT;	/* bytes to bits */
> +	arclen *=3D 7;		/* bytes to bits */
> +
> +	/*
> +	 * The arc has the number of bits
> +	 * cannot be represented using supplied return value type.
> +	 */
> +	if(arclen > rvsize) {
> +		if(arclen > (rvsize + CHAR_BIT)) {
> +			errno =3D ERANGE;	/* Overflow */
> +			return -1;
> +		} else {
> +			/*
> +			 * Even if the number of bits in the arc
> representation
> +			 * is higher than the width of supplied *
> return value
> +			 * type, there is still possible to fit it
> when there
> +			 * are few unused high bits in the arc value
> +			 * representaion.
> +			 *=20
> +			 * Moreover, there is a possibility that the
> +			 * number could actually fit the arc space,
> given
> +			 * that add is negative, but we don't handle
> +			 * such "temporary lack of precision"
> situation here.
> +			 * May be considered as a bug.
> +			 */
> +			uint8_t mask =3D (0xff << (7-(arclen -
> rvsize))) & 0x7f;
> +			if((*arcbuf & mask)) {
> +				errno =3D ERANGE;	/* Overflow */
> +				return -1;
> +			}
> +			/* Fool the routine computing unused bits */
> +			arclen -=3D 7;
> +			cache =3D *arcbuf & 0x7f;
> +			arcbuf++;
> +		}
> +	}
> +
> +	/* Faster path for common size */
> +	if(rvsize =3D=3D (CHAR_BIT * sizeof(unsigned long))) {
> +		unsigned long accum;
> +		/* Gather all bits into the accumulator */
> +		for(accum =3D cache; arcbuf < arcend; arcbuf++)
> +			accum =3D (accum << 7) | (*arcbuf & ~0x80);
> +		if(accum < (unsigned)-add) {
> +			errno =3D ERANGE;	/* Overflow */
> +			return -1;
> +		}
> +		*(unsigned long *)(void *)rvbuf =3D accum +
> add;	/* alignment OK! */
> +		return 0;
> +	}
> +
> +#ifndef	WORDS_BIGENDIAN
> +	if(*(unsigned char *)&LE) {	/* Little endian (x86) */
> +		/* "Convert" to big endian */
> +		rvbuf +=3D rvsize / CHAR_BIT - 1;
> +		rvstart--;
> +		inc =3D -1;	/* Descending */
> +	} else
> +#endif	/* !WORDS_BIGENDIAN */
> +		inc =3D +1;	/* Big endian is known [at compile
> time] */ +
> +	{
> +		int bits;	/* typically no more than 3-4 bits
> */ +
> +		/* Clear the high unused bits */
> +		for(bits =3D rvsize - arclen;
> +			bits > CHAR_BIT;
> +				rvbuf +=3D inc, bits -=3D CHAR_BIT)
> +				*rvbuf =3D 0;
> +
> +		/* Fill the body of a value */
> +		for(; arcbuf < arcend; arcbuf++) {
> +			cache =3D (cache << 7) | (*arcbuf & 0x7f);
> +			bits +=3D 7;
> +			if(bits >=3D CHAR_BIT) {
> +				bits -=3D CHAR_BIT;
> +				*rvbuf =3D (cache >> bits);
> +				rvbuf +=3D inc;
> +			}
> +		}
> +		if(bits) {
> +			*rvbuf =3D cache;
> +			rvbuf +=3D inc;
> +		}
> +	}
> +
> +	if(add) {
> +		for(rvbuf -=3D inc; rvbuf !=3D rvstart; rvbuf -=3D inc) {
> +			int v =3D add + *rvbuf;
> +			if(v & ((unsigned)~0 << CHAR_BIT)) {
> +				*rvbuf =3D (unsigned char)(v + (1 <<
> CHAR_BIT));
> +				add =3D -1;
> +			} else {
> +				*rvbuf =3D v;
> +				break;
> +			}
> +		}
> +		if(rvbuf =3D=3D rvstart) {
> +			/* No space to carry over */
> +			errno =3D ERANGE;	/* Overflow */
> +			return -1;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +ssize_t
> +OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int
> add,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	char scratch[64];	/* Conservative estimate */
> +	unsigned long accum;	/* Bits accumulator */
> +	char *p;		/* Position in the scratch buffer */
> +
> +	if(OBJECT_IDENTIFIER_get_single_arc(arcbuf, arclen, add,
> +			&accum, sizeof(accum)))
> +		return -1;
> +
> +	if(accum) {
> +		ssize_t len;
> +
> +		/* Fill the scratch buffer in reverse. */
> +		p =3D scratch + sizeof(scratch);
> +		for(; accum; accum /=3D 10)
> +			*(--p) =3D (char)(accum % 10) + 0x30; /* Put a
> digit */ +
> +		len =3D sizeof(scratch) - (p - scratch);
> +		if(cb(p, len, app_key) < 0)
> +			return -1;
> +		return len;
> +	} else {
> +		*scratch =3D 0x30;
> +		if(cb(scratch, 1, app_key) < 0)
> +			return -1;
> +		return 1;
> +	}
> +}
> +
> +int
> +OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen, int
> add,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +
> +	if(OBJECT_IDENTIFIER__dump_arc(arcbuf, arclen, add, cb,
> app_key) < 0)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static ssize_t
> +OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st,
> asn_app_consume_bytes_f *cb, void *app_key) {
> +	ssize_t wrote_len =3D 0;
> +	int startn;
> +	int add =3D 0;
> +	int i;
> +
> +	for(i =3D 0, startn =3D 0; i < st->size; i++) {
> +		uint8_t b =3D st->buf[i];
> +		if((b & 0x80))			/*
> Continuation expected */
> +			continue;
> +
> +		if(startn =3D=3D 0) {
> +			/*
> +			 * First two arcs are encoded through the
> backdoor.
> +			 */
> +			if(i) {
> +				add =3D -80;
> +				if(cb("2", 1, app_key) < 0) return
> -1;
> +			} else if(b <=3D 39) {
> +				add =3D 0;
> +				if(cb("0", 1, app_key) < 0) return
> -1;
> +			} else if(b < 79) {
> +				add =3D -40;
> +				if(cb("1", 1, app_key) < 0) return
> -1;
> +			} else {
> +				add =3D -80;
> +				if(cb("2", 1, app_key) < 0) return
> -1;
> +			}
> +			wrote_len +=3D 1;
> +		}
> +
> +		if(cb(".", 1, app_key) < 0)	/* Separate arcs
> */
> +			return -1;
> +
> +		add =3D OBJECT_IDENTIFIER__dump_arc(&st->buf[startn],
> +				i - startn + 1, add, cb, app_key);
> +		if(add < 0) return -1;
> +		wrote_len +=3D 1 + add;
> +		startn =3D i + 1;
> +		add =3D 0;
> +	}
> +
> +	return wrote_len;
> +}
> +
> +static enum xer_pbd_rval
> +OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void
> *sptr, const void *chunk_buf, size_t chunk_size) {
> +	OBJECT_IDENTIFIER_t *st =3D (OBJECT_IDENTIFIER_t *)sptr;
> +	const char *chunk_end =3D (const char *)chunk_buf + chunk_size;
> +	const char *endptr;
> +	long s_arcs[10];
> +	long *arcs =3D s_arcs;
> +	int arcs_count;
> +	int ret;
> +
> +	(void)td;
> +
> +	arcs_count =3D OBJECT_IDENTIFIER_parse_arcs(
> +		(const char *)chunk_buf, chunk_size, arcs,
> +			sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
> +	if(arcs_count < 0) {
> +		/* Expecting more than zero arcs */
> +		return XPBD_BROKEN_ENCODING;
> +	} else if(arcs_count =3D=3D 0) {
> +		return XPBD_NOT_BODY_IGNORE;
> +	}
> +	assert(endptr =3D=3D chunk_end);
> +
> +	if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
> +		arcs =3D (long *)MALLOC(arcs_count * sizeof(long));
> +		if(!arcs) return XPBD_SYSTEM_FAILURE;
> +		ret =3D OBJECT_IDENTIFIER_parse_arcs(
> +			(const char *)chunk_buf, chunk_size,
> +			arcs, arcs_count, &endptr);
> +		if(ret !=3D arcs_count)
> +			return XPBD_SYSTEM_FAILURE;	/*
> assert?.. */
> +	}
> +
> +	/*
> +	 * Convert arcs into BER representation.
> +	 */
> +	ret =3D OBJECT_IDENTIFIER_set_arcs(st, arcs, sizeof(*arcs),
> arcs_count);
> +	if(arcs !=3D s_arcs) FREEMEM(arcs);
> +
> +	return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
> +}
> +
> +asn_dec_rval_t
> +OBJECT_IDENTIFIER_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td, void **sptr, const char
> *opt_mname,
> +		const void *buf_ptr, size_t size) {
> +
> +	return xer_decode_primitive(opt_codec_ctx, td,
> +		sptr, sizeof(OBJECT_IDENTIFIER_t), opt_mname,
> +			buf_ptr, size,
> OBJECT_IDENTIFIER__xer_body_decode); +}
> +
> +asn_enc_rval_t
> +OBJECT_IDENTIFIER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
> +	int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	const OBJECT_IDENTIFIER_t *st =3D (const OBJECT_IDENTIFIER_t
> *)sptr;
> +	asn_enc_rval_t er;
> +
> +	(void)ilevel;
> +	(void)flags;
> +
> +	if(!st || !st->buf)
> +		ASN__ENCODE_FAILED;
> +
> +	er.encoded =3D OBJECT_IDENTIFIER__dump_body(st, cb, app_key);
> +	if(er.encoded < 0) ASN__ENCODE_FAILED;
> +
> +	ASN__ENCODED_OK(er);
> +}
> +
> +int
> +OBJECT_IDENTIFIER_print(asn_TYPE_descriptor_t *td, const void *sptr,
> +	int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
> +	const OBJECT_IDENTIFIER_t *st =3D (const OBJECT_IDENTIFIER_t
> *)sptr; +
> +	(void)td;	/* Unused argument */
> +	(void)ilevel;	/* Unused argument */
> +
> +	if(!st || !st->buf)
> +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
> +
> +	/* Dump preamble */
> +	if(cb("{ ", 2, app_key) < 0)
> +		return -1;
> +
> +	if(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0)
> +		return -1;
> +
> +	return (cb(" }", 2, app_key) < 0) ? -1 : 0;
> +}
> +
> +int
> +OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *oid, void
> *arcs,
> +		unsigned int arc_type_size, unsigned int arc_slots) {
> +	void *arcs_end =3D (char *)arcs + (arc_type_size * arc_slots);
> +	int num_arcs =3D 0;
> +	int startn =3D 0;
> +	int add =3D 0;
> +	int i;
> +
> +	if(!oid || !oid->buf || (arc_slots && arc_type_size <=3D 1)) {
> +		errno =3D EINVAL;
> +		return -1;
> +	}
> +
> +	for(i =3D 0; i < oid->size; i++) {
> +		uint8_t b =3D oid->buf[i];
> +		if((b & 0x80))			/*
> Continuation expected */
> +			continue;
> +
> +		if(num_arcs =3D=3D 0) {
> +			/*
> +			 * First two arcs are encoded through the
> backdoor.
> +			 */
> +			unsigned LE =3D 1;	/* Little endian */
> +			int first_arc;
> +			num_arcs++;
> +			if(!arc_slots) { num_arcs++; continue; }
> +
> +			if(i) first_arc =3D 2;
> +			else if(b <=3D 39) first_arc =3D 0;
> +			else if(b < 79)	first_arc =3D 1;
> +			else first_arc =3D 2;
> +
> +			add =3D -40 * first_arc;
> +			memset(arcs, 0, arc_type_size);
> +			*(unsigned char *)((char *)arcs
> +				+ ((*(char *)&LE)?0:(arc_type_size -
> 1)))
> +					=3D first_arc;
> +			arcs =3D ((char *)arcs) + arc_type_size;
> +		}
> +
> +		/* Decode, if has space */
> +		if(arcs < arcs_end) {
> +
> if(OBJECT_IDENTIFIER_get_single_arc(&oid->buf[startn],
> +				i - startn + 1, add,
> +					arcs, arc_type_size))
> +				return -1;
> +			startn =3D i + 1;
> +			arcs =3D ((char *)arcs) + arc_type_size;
> +			add =3D 0;
> +		}
> +		num_arcs++;
> +	}
> +
> +	return num_arcs;
> +}
> +
> +
> +/*
> + * Save the single value as an object identifier arc.
> + */
> +int
> +OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, const void
> *arcval, unsigned int arcval_size, int prepared_order) {
> +	/*
> +	 * The following conditions must hold:
> +	 * assert(arcval);
> +	 * assert(arcval_size > 0);
> +	 * assert(arcval_size <=3D 16);
> +	 * assert(arcbuf);
> +	 */
> +#ifdef	WORDS_BIGENDIAN
> +	const unsigned isLittleEndian =3D 0;
> +#else
> +	unsigned LE =3D 1;
> +	unsigned isLittleEndian =3D *(char *)&LE;
> +#endif
> +	const uint8_t *tend, *tp;
> +	unsigned int cache;
> +	uint8_t *bp =3D arcbuf;
> +	int bits;
> +	uint8_t buffer[16];
> +
> +	if(isLittleEndian && !prepared_order) {
> +		const uint8_t *a =3D (const unsigned char *)arcval +
> arcval_size - 1;
> +		const uint8_t *aend =3D (const uint8_t *)arcval;
> +		uint8_t *msb =3D buffer + arcval_size - 1;
> +		uint8_t *tb;
> +		for(tb =3D buffer; a >=3D aend; tb++, a--)
> +			if((*tb =3D *a) && (tb < msb))
> +				msb =3D tb;
> +		tend =3D &buffer[arcval_size];
> +		tp =3D msb;	/* Most significant non-zero byte */
> +	} else {
> +		/* Look for most significant non-zero byte */
> +		tend =3D (const unsigned char *)arcval + arcval_size;
> +		for(tp =3D (const uint8_t *)arcval; tp < tend - 1;
> tp++)
> +			if(*tp) break;
> +	}
> +
> +	/*
> +	 * Split the value in 7-bits chunks.
> +	 */
> +	bits =3D ((tend - tp) * CHAR_BIT) % 7;
> +	if(bits) {
> +		cache =3D *tp >> (CHAR_BIT - bits);
> +		if(cache) {
> +			*bp++ =3D cache | 0x80;
> +			cache =3D *tp++;
> +			bits =3D CHAR_BIT - bits;
> +		} else {
> +			bits =3D -bits;
> +		}
> +	} else {
> +		cache =3D 0;
> +	}
> +	for(; tp < tend; tp++) {
> +		cache =3D (cache << CHAR_BIT) + *tp;
> +		bits +=3D CHAR_BIT;
> +		while(bits >=3D 7) {
> +			bits -=3D 7;
> +			*bp++ =3D 0x80 | (cache >> bits);
> +		}
> +	}
> +	if(bits) *bp++ =3D cache;
> +	bp[-1] &=3D 0x7f;	/* Clear the last bit */
> +
> +	return bp - arcbuf;
> +}
> +
> +int
> +OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid, const void
> *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
> +	uint8_t *buf;
> +	uint8_t *bp;
> +	unsigned LE =3D 1;	/* Little endian (x86) */
> +	unsigned isLittleEndian =3D *((char *)&LE);
> +	unsigned int arc0;
> +	unsigned int arc1;
> +	unsigned size;
> +	unsigned i;
> +
> +	if(!oid || !arcs || arc_type_size < 1
> +	|| arc_type_size > 16
> +	|| arc_slots < 2) {
> +		errno =3D EINVAL;
> +		return -1;
> +	}
> +
> +	switch(arc_type_size) {
> +	case sizeof(char):
> +		arc0 =3D ((const unsigned char *)arcs)[0];
> +		arc1 =3D ((const unsigned char *)arcs)[1];
> +		break;
> +	case sizeof(short):
> +		arc0 =3D ((const unsigned short *)arcs)[0];
> +		arc1 =3D ((const unsigned short *)arcs)[1];
> +		break;
> +	case sizeof(int):
> +		arc0 =3D ((const unsigned int *)arcs)[0];
> +		arc1 =3D ((const unsigned int *)arcs)[1];
> +		break;
> +	default:
> +		arc1 =3D arc0 =3D 0;
> +		if(isLittleEndian) {	/* Little endian (x86) */
> +			const unsigned char *ps, *pe;
> +			/* If more significant bytes are present,
> +			 * make them > 255 quick */
> +			for(ps =3D (const unsigned char *)arcs + 1, pe
> =3D ps+arc_type_size;
> +					ps < pe; ps++)
> +				arc0 |=3D *ps, arc1 |=3D *(ps +
> arc_type_size);
> +			arc0 <<=3D CHAR_BIT, arc1 <<=3D CHAR_BIT;
> +			arc0 =3D *((const unsigned char *)arcs + 0);
> +			arc1 =3D *((const unsigned char *)arcs +
> arc_type_size);
> +		} else {
> +			const unsigned char *ps, *pe;
> +			/* If more significant bytes are present,
> +			 * make them > 255 quick */
> +			for(ps =3D (const unsigned char *)arcs, pe =3D
> ps+arc_type_size - 1; ps < pe; ps++)
> +				arc0 |=3D *ps, arc1 |=3D *(ps +
> arc_type_size);
> +			arc0 =3D *((const unsigned char *)arcs +
> arc_type_size - 1);
> +			arc1 =3D *((const unsigned char *)arcs
> +(arc_type_size<< 1)-1);
> +		}
> +	}
> +
> +	/*
> +	 * The previous chapter left us with the first and the
> second arcs.
> +	 * The values are not precise (that is, they are valid only
> if
> +	 * they're less than 255), but OK for the purposes of making
> +	 * the sanity test below.
> +	 */
> +	if(arc0 <=3D 1) {
> +		if(arc1 >=3D 39) {
> +			/* 8.19.4: At most 39 subsequent values
> (including 0) */
> +			errno =3D ERANGE;
> +			return -1;
> +		}
> +	} else if(arc0 > 2) {
> +		/* 8.19.4: Only three values are allocated from the
> root node */
> +		errno =3D ERANGE;
> +		return -1;
> +	}
> +	/*
> +	 * After above tests it is known that the value of arc0 is
> completely
> +	 * trustworthy (0..2). However, the arc1's value is still
> meaningless.
> +	 */
> +
> +	/*
> +	 * Roughly estimate the maximum size necessary to encode
> these arcs.
> +	 * This estimation implicitly takes in account the following
> facts,
> +	 * that cancel each other:
> +	 * 	* the first two arcs are encoded in a single
> value.
> +	 * 	* the first value may require more space (+1 byte)
> +	 * 	* the value of the first arc which is in range
> (0..2)
> +	 */
> +	size =3D ((arc_type_size * CHAR_BIT + 6) / 7) * arc_slots;
> +	bp =3D buf =3D (uint8_t *)MALLOC(size + 1);
> +	if(!buf) {
> +		/* ENOMEM */
> +		return -1;
> +	}
> +
> +	/*
> +	 * Encode the first two arcs.
> +	 * These require special treatment.
> +	 */
> +	{
> +		uint8_t *tp;
> +		uint8_t first_value[1 + 16];	/* of two arcs */
> +		uint8_t *fv =3D first_value;
> +
> +		/*
> +		 * Simulate first_value =3D arc0 * 40 + arc1;
> +		 */
> +		/* Copy the second (1'st) arcs[1] into the
> first_value */
> +		*fv++ =3D 0;
> +		arcs =3D ((const char *)arcs) + arc_type_size;
> +		if(isLittleEndian) {
> +			const uint8_t *aend =3D (const unsigned char
> *)arcs - 1;
> +			const uint8_t *a1 =3D (const unsigned char
> *)arcs + arc_type_size - 1;
> +			for(; a1 > aend; fv++, a1--) *fv =3D *a1;
> +		} else {
> +			const uint8_t *a1 =3D (const uint8_t *)arcs;
> +			const uint8_t *aend =3D a1 + arc_type_size;
> +			for(; a1 < aend; fv++, a1++) *fv =3D *a1;
> +		}
> +		/* Increase the first_value by arc0 */
> +		arc0 *=3D 40;	/* (0..80) */
> +		for(tp =3D first_value + arc_type_size; tp >=3D
> first_value; tp--) {
> +			unsigned int v =3D *tp;
> +			v +=3D arc0;
> +			*tp =3D v;
> +			if(v >=3D (1 << CHAR_BIT)) arc0 =3D v >>
> CHAR_BIT;
> +			else break;
> +		}
> +
> +		assert(tp >=3D first_value);
> +
> +		bp +=3D OBJECT_IDENTIFIER_set_single_arc(bp,
> first_value,
> +			fv - first_value, 1);
> + 	}
> +
> +	/*
> +	 * Save the rest of arcs.
> +	 */
> +	for(arcs =3D ((const char *)arcs) + arc_type_size, i =3D 2;
> +		i < arc_slots;
> +			i++, arcs =3D ((const char *)arcs) +
> arc_type_size) {
> +		bp +=3D OBJECT_IDENTIFIER_set_single_arc(bp,
> +			arcs, arc_type_size, 0);
> +	}
> +
> +	assert((unsigned)(bp - buf) <=3D size);
> +
> +	/*
> +	 * Replace buffer.
> +	 */
> +	oid->size =3D bp - buf;
> +	bp =3D oid->buf;
> +	oid->buf =3D buf;
> +	if(bp) FREEMEM(bp);
> +
> +	return 0;
> +}
> +
> +
> +int
> +OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t
> oid_txt_length,
> +	long *arcs, unsigned int arcs_slots, const char
> **opt_oid_text_end) {
> +	unsigned int arcs_count =3D 0;
> +	const char *oid_end;
> +	enum {
> +		ST_LEADSPACE,
> +		ST_TAILSPACE,
> +		ST_AFTERVALUE,	/* Next character ought to be
> '.' or a space */
> +		ST_WAITDIGITS 	/* Next character is expected
> to be a digit */
> +	} state =3D ST_LEADSPACE;
> +
> +	if(!oid_text || oid_txt_length < -1 || (arcs_slots
> && !arcs)) {
> +		if(opt_oid_text_end) *opt_oid_text_end =3D oid_text;
> +		errno =3D EINVAL;
> +		return -1;
> +	}
> +
> +	if(oid_txt_length =3D=3D -1)
> +		oid_txt_length =3D strlen(oid_text);
> +
> +#define	_OID_CAPTURE_ARC(oid_text, oid_end)		do
> {	\
> +	const char *endp =3D oid_end;				\
> +	long value;						\
> +	switch(asn_strtol_lim(oid_text, &endp, &value)) {	\
> +	case ASN_STRTOL_EXTRA_DATA:				\
> +	case ASN_STRTOL_OK:					\
> +		if(arcs_count < arcs_slots)			\
> +			arcs[arcs_count] =3D value;		\
> +		arcs_count++;
> \
> +		oid_text =3D endp - 1;				\
> +
> break;						\
> +	case ASN_STRTOL_ERROR_RANGE:				\
> +		if(opt_oid_text_end)				\
> +			*opt_oid_text_end =3D oid_text;
> \
> +		errno =3D
> ERANGE;					\
> +		return -1;					\
> +	case ASN_STRTOL_ERROR_INVAL:				\
> +	case ASN_STRTOL_EXPECT_MORE:				\
> +		if(opt_oid_text_end)				\
> +			*opt_oid_text_end =3D oid_text;
> \
> +		errno =3D
> EINVAL;					\
> +		return -1;					\
> +	}							\
> +  } while(0)
> +
> +	for(oid_end =3D oid_text + oid_txt_length; oid_text<oid_end;
> oid_text++) {
> +	    switch(*oid_text) {
> +	    case 0x09: case 0x0a: case 0x0d: case 0x20:	/*
> whitespace */
> +		switch(state) {
> +		case ST_LEADSPACE:
> +		case ST_TAILSPACE:
> +			continue;
> +		case ST_AFTERVALUE:
> +			state =3D ST_TAILSPACE;
> +			continue;
> +		case ST_WAITDIGITS:
> +			break;	/* Digits expected after ".",
> got whitespace */
> +		}
> +		break;
> +	    case 0x2e:	/* '.' */
> +		switch(state) {
> +		case ST_LEADSPACE:
> +		case ST_TAILSPACE:
> +		case ST_WAITDIGITS:
> +			if(opt_oid_text_end)
> +				*opt_oid_text_end =3D oid_text;
> +			errno =3D EINVAL;	/* Broken OID */
> +			return -1;
> +			break;
> +		case ST_AFTERVALUE:
> +			state =3D ST_WAITDIGITS;
> +			continue;
> +		}
> +		break;
> +	    case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
> +	    case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
> +		switch(state) {
> +		case ST_TAILSPACE:
> +		case ST_AFTERVALUE:
> +			if(opt_oid_text_end)
> +				*opt_oid_text_end =3D oid_text;
> +			errno =3D EINVAL;	/* "1. 1" =3D> broken
> OID */
> +			return -1;
> +		case ST_LEADSPACE:
> +		case ST_WAITDIGITS:
> +			_OID_CAPTURE_ARC(oid_text, oid_end);
> +			state =3D ST_AFTERVALUE;
> +			continue;
> +		}
> +		break;
> +	    default:
> +		/* Unexpected symbols */
> +		state =3D ST_WAITDIGITS;
> +		break;
> +	    } /* switch() */
> +	    break;
> +	} /* for() */
> +
> +
> +	if(opt_oid_text_end) *opt_oid_text_end =3D oid_text;
> +
> +	/* Finalize last arc */
> +	switch(state) {
> +	case ST_LEADSPACE:
> +		return 0; /* No OID found in input data */
> +	case ST_WAITDIGITS:
> +		errno =3D EINVAL;	/* Broken OID */
> +		return -1;
> +	case ST_AFTERVALUE:
> +	case ST_TAILSPACE:
> +		return arcs_count;
> +	}
> +
> +	errno =3D EINVAL;	/* Broken OID */
> +	return -1;
> +}
> +
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h
> b/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h new file mode 100644
> index 000000000000..c2c6373e3bc2
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/OBJECT_IDENTIFIER.h
> @@ -0,0 +1,139 @@
> +/*-
> + * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
> + * 	All rights reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	_OBJECT_IDENTIFIER_H_
> +#define	_OBJECT_IDENTIFIER_H_
> +
> +#include <asn_application.h>
> +#include <asn_codecs_prim.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef ASN__PRIMITIVE_TYPE_t OBJECT_IDENTIFIER_t;
> +
> +extern asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER;
> +
> +asn_struct_print_f OBJECT_IDENTIFIER_print;
> +asn_constr_check_f OBJECT_IDENTIFIER_constraint;
> +der_type_encoder_f OBJECT_IDENTIFIER_encode_der;
> +xer_type_decoder_f OBJECT_IDENTIFIER_decode_xer;
> +xer_type_encoder_f OBJECT_IDENTIFIER_encode_xer;
> +
> +/**********************************
> + * Some handy conversion routines *
> + **********************************/
> +
> +/*
> + * This function fills an (_arcs) array with OBJECT IDENTIFIER arcs
> + * up to specified (_arc_slots) elements.
> + *=20
> + * EXAMPLE:
> + * 	void print_arcs(OBJECT_IDENTIFIER_t *oid) {
> + * 		unsigned long fixed_arcs[10];	// Try with
> fixed space first
> + * 		unsigned long *arcs =3D fixed_arcs;
> + * 		int arc_type_size =3D
> sizeof(fixed_arcs[0]);	// sizeof(long)
> + * 		int arc_slots =3D
> sizeof(fixed_arcs)/sizeof(fixed_arcs[0]); // 10
> + * 		int count;	// Real number of arcs.
> + * 		int i;
> + *=20
> + * 		count =3D OBJECT_IDENTIFIER_get_arcs(oid, arcs,
> + * 			arc_type_size, arc_slots);
> + * 		// If necessary, reallocate arcs array and try
> again.
> + * 		if(count > arc_slots) {
> + * 			arc_slots =3D count;
> + * 			arcs =3D malloc(arc_type_size * arc_slots);
> + * 			if(!arcs) return;
> + * 			count =3D OBJECT_IDENTIFIER_get_arcs(oid,
> arcs,
> + * 				arc_type_size, arc_slots);
> + * 			assert(count =3D=3D arc_slots);
> + * 		}
> + *=20
> + * 		// Print the contents of the arcs array.
> + * 		for(i =3D 0; i < count; i++)
> + * 			printf("%d\n", arcs[i]);
> + *=20
> + * 		// Avoid memory leak.
> + * 		if(arcs !=3D fixed_arcs) free(arcs);
> + * 	}
> + *=20
> + * RETURN VALUES:
> + * -1/EINVAL:	Invalid arguments (oid is missing)
> + * -1/ERANGE:	One or more arcs have value out of array cell
> type range.
> + * >=3D0:		Number of arcs contained in the OBJECT
> IDENTIFIER
> + *=20
> + * WARNING: The function always returns the real number of arcs,
> + * even if there is no sufficient (_arc_slots) provided.
> + */
> +int OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *_oid,
> +	void *_arcs,			/* e.g., unsigned int
> arcs[N] */
> +	unsigned int _arc_type_size,	/* e.g., sizeof(arcs[0])
> */
> +	unsigned int _arc_slots		/* e.g., N */);
> +
> +/*
> + * This functions initializes the OBJECT IDENTIFIER object with
> + * the given set of arcs.
> + * The minimum of two arcs must be present; some restrictions apply.
> + * RETURN VALUES:
> + * -1/EINVAL:	Invalid arguments
> + * -1/ERANGE:	The first two arcs do not conform to ASN.1
> restrictions.
> + * -1/ENOMEM:	Memory allocation failed
> + * 0:		The object was initialized with new arcs.
> + */
> +int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *_oid,
> +	const void *_arcs,		/* e.g., unsigned int
> arcs[N] */
> +	unsigned int _arc_type_size,	/* e.g., sizeof(arcs[0])
> */
> +	unsigned int _arc_slots		/* e.g., N */);
> +
> +/*
> + * Print the specified OBJECT IDENTIFIER arc.
> + */
> +int OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen,
> +	int add, /* Arbitrary offset, required to process the first
> two arcs */
> +	asn_app_consume_bytes_f *cb, void *app_key);
> +
> +/* Same as above, but returns the number of written digits, instead
> of 0 */ +ssize_t OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf,
> int arclen, int add,
> +	asn_app_consume_bytes_f *cb, void *app_key);
> +
> +/*
> + * Parse the OBJECT IDENTIFIER textual representation
> ("1.3.6.1.4.1.9363").
> + * No arc can exceed the (0..signed_long_max) range (typically,
> 0..2G if L32).
> + * This function is not specific to OBJECT IDENTIFIER, it may be
> used to parse
> + * the RELATIVE-OID data, or any other data consisting of
> dot-separated
> + * series of numeric values.
> + *
> + * If (oid_txt_length =3D=3D -1), the strlen() will be invoked to
> determine the
> + * size of the (oid_text) string.
> + *=20
> + * After return, the optional (opt_oid_text_end) is set to the
> character after
> + * the last parsed one. (opt_oid_text_end) is never less than
> (oid_text).
> + *=20
> + * RETURN VALUES:
> + *   -1:	Parse error.
> + * >=3D 0:	Number of arcs contained in the OBJECT IDENTIFIER.
> + *=20
> + * WARNING: The function always returns the real number of arcs,
> + * even if there is no sufficient (_arc_slots) provided.
> + * This is useful for (_arc_slots) value estimation.
> + */
> +int OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t
> oid_txt_length,
> +	long arcs[], unsigned int arcs_slots, const char
> **opt_oid_text_end); +
> +/*
> + * Internal functions.
> + * Used by RELATIVE-OID implementation in particular.
> + */
> +int OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned
> int arclen,
> +	signed int add, void *value, unsigned int value_size);
> +int OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf,
> +	const void *arcval, unsigned int arcval_size, int
> _prepared_order); +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _OBJECT_IDENTIFIER_H_ */
> diff --git a/libkmod/pkcs7/asn1c-gen/OCTET_STRING.c
> b/libkmod/pkcs7/asn1c-gen/OCTET_STRING.c new file mode 100644
> index 000000000000..5420dedecab2
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/OCTET_STRING.c
> @@ -0,0 +1,1807 @@
> +/*-
> + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
> + * All rights reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <OCTET_STRING.h>
> +#include <BIT_STRING.h>	/* for .bits_unused member */
> +#include <errno.h>
> +
> +/*
> + * OCTET STRING basic type description.
> + */
> +static const ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
> +};
> +static const asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs
> =3D {
> +	sizeof(OCTET_STRING_t),
> +	offsetof(OCTET_STRING_t, _asn_ctx),
> +	ASN_OSUBV_STR
> +};
> +static const asn_per_constraints_t asn_DEF_OCTET_STRING_constraints
> =3D {
> +	{ APC_CONSTRAINED, 8, 8, 0, 255 },
> +	{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
> +	0, 0
> +};
> +asn_TYPE_descriptor_t asn_DEF_OCTET_STRING =3D {
> +	"OCTET STRING",		/* Canonical name */
> +	"OCTET_STRING",		/* XML tag name */
> +	OCTET_STRING_free,
> +	OCTET_STRING_print,	/* non-ascii stuff, generally */
> +	asn_generic_no_constraint,
> +	OCTET_STRING_decode_ber,
> +	OCTET_STRING_encode_der,
> +	OCTET_STRING_decode_xer_hex,
> +	OCTET_STRING_encode_xer,
> +	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
> +	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
> +	0, /* Use generic outmost tag fetcher */
> +	asn_DEF_OCTET_STRING_tags,
> +	sizeof(asn_DEF_OCTET_STRING_tags)
> +	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
> +	asn_DEF_OCTET_STRING_tags,	/* Same as above */
> +	sizeof(asn_DEF_OCTET_STRING_tags)
> +	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	&asn_DEF_OCTET_STRING_specs
> +};
> +
> +#undef	_CH_PHASE
> +#undef	NEXT_PHASE
> +#undef	PREV_PHASE
> +#define	_CH_PHASE(ctx, inc) do
> {					\
> +		if(ctx->phase =3D=3D
> 0)					\
> +			ctx->context =3D
> 0;				\
> +		ctx->phase +=3D
> inc;					\
> +	} while(0)
> +#define	NEXT_PHASE(ctx)	_CH_PHASE(ctx, +1)
> +#define	PREV_PHASE(ctx)	_CH_PHASE(ctx, -1)
> +
> +#undef	ADVANCE
> +#define	ADVANCE(num_bytes)	do
> {					\
> +		size_t num =3D
> (num_bytes);				\
> +		buf_ptr =3D ((const char *)buf_ptr) +
> num;		\
> +		size -=3D
> num;						\
> +		consumed_myself +=3D
> num;					\
> +	} while(0)
> +
> +#undef	RETURN
> +#define	RETURN(_code)	do
> {						\
> +		asn_dec_rval_t
> tmprval;					\
> +		tmprval.code =3D
> _code;					\
> +		tmprval.consumed =3D
> consumed_myself;			\
> +		return
> tmprval;						\
> +	} while(0)
> +
> +#undef	APPEND
> +#define	APPEND(bufptr, bufsize)	do
> {					\
> +		size_t _bs =3D (bufsize);		/* Append
> size */	\
> +		size_t _ns =3D ctx->context;	/* Allocated now
> */	\
> +		size_t _es =3D st->size + _bs;	/* Expected size
> */	\
> +		/* int is really a typeof(st->size):
> */			\
> +		if((int)_es < 0)
> RETURN(RC_FAIL);			\
> +		if(_ns <=3D _es)
> {					\
> +			void
> *ptr;					\
> +			/* Be nice and round to the memory allocator
> */	\
> +			do { _ns =3D _ns ? _ns << 1 :
> 16; }		\
> +			    while(_ns <=3D
> _es);				\
> +			/* int is really a typeof(st->size):
> */		\
> +			if((int)_ns < 0)
> RETURN(RC_FAIL);		\
> +			ptr =3D REALLOC(st->buf,
> _ns);			\
> +			if(ptr)
> {					\
> +				st->buf =3D (uint8_t
> *)ptr;		\
> +				ctx->context =3D
> _ns;			\
> +			} else
> {					\
> +
> RETURN(RC_FAIL);			\
> +			}
> \
> +			ASN_DEBUG("Reallocating into %ld",
> (long)_ns);	\
> +		}
> \
> +		memcpy(st->buf + st->size, bufptr,
> _bs);		\
> +		/* Convenient nul-termination
> */			\
> +		st->buf[_es] =3D
> '\0';					\
> +		st->size =3D
> _es;						\
> +	} while(0)
> +
> +/*
> + * The main reason why ASN.1 is still alive is that too much time
> and effort
> + * is necessary for learning it more or less adequately, thus
> creating a gut
> + * necessity to demonstrate that aquired skill everywhere afterwards.
> + * No, I am not going to explain what the following stuff is.
> + */
> +struct _stack_el {
> +	ber_tlv_len_t	left;	/* What's left to read (or
> -1) */
> +	ber_tlv_len_t	got;	/* What was actually
> processed */
> +	int	cont_level;	/* Depth of subcontainment */
> +	int	want_nulls;	/* Want null "end of content"
> octets? */
> +	int	bits_chopped;	/* Flag in BIT STRING mode */
> +	ber_tlv_tag_t	tag;	/* For debugging purposes */
> +	struct _stack_el *prev;
> +	struct _stack_el *next;
> +};
> +struct _stack {
> +	struct _stack_el *tail;
> +	struct _stack_el *cur_ptr;
> +};
> +
> +static struct _stack_el *
> +OS__add_stack_el(struct _stack *st) {
> +	struct _stack_el *nel;
> +
> +	/*
> +	 * Reuse the old stack frame or allocate a new one.
> +	 */
> +	if(st->cur_ptr && st->cur_ptr->next) {
> +		nel =3D st->cur_ptr->next;
> +		nel->bits_chopped =3D 0;
> +		nel->got =3D 0;
> +		/* Retain the nel->cont_level, it's correct. */
> +	} else {
> +		nel =3D (struct _stack_el *)CALLOC(1, sizeof(struct
> _stack_el));
> +		if(nel =3D=3D NULL)
> +			return NULL;
> +=09
> +		if(st->tail) {
> +			/* Increase a subcontainment depth */
> +			nel->cont_level =3D st->tail->cont_level + 1;
> +			st->tail->next =3D nel;
> +		}
> +		nel->prev =3D st->tail;
> +		st->tail =3D nel;
> +	}
> +
> +	st->cur_ptr =3D nel;
> +
> +	return nel;
> +}
> +
> +static struct _stack *
> +_new_stack() {
> +	return (struct _stack *)CALLOC(1, sizeof(struct _stack));
> +}
> +
> +/*
> + * Decode OCTET STRING type.
> + */
> +asn_dec_rval_t
> +OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td,
> +	void **sptr, const void *buf_ptr, size_t size, int tag_mode)
> {
> +	asn_OCTET_STRING_specifics_t *specs =3D td->specifics
> +				? (asn_OCTET_STRING_specifics_t
> *)td->specifics
> +				: &asn_DEF_OCTET_STRING_specs;
> +	BIT_STRING_t *st =3D (BIT_STRING_t *)*sptr;
> +	asn_dec_rval_t rval;
> +	asn_struct_ctx_t *ctx;
> +	ssize_t consumed_myself =3D 0;
> +	struct _stack *stck;		/* Expectations stack
> structure */
> +	struct _stack_el *sel =3D 0;	/* Stack element */
> +	int tlv_constr;
> +	enum asn_OS_Subvariant type_variant =3D specs->subvariant;
> +
> +	ASN_DEBUG("Decoding %s as %s (frame %ld)",
> +		td->name,
> +		(type_variant =3D=3D ASN_OSUBV_STR) ?
> +			"OCTET STRING" : "OS-SpecialCase",
> +		(long)size);
> +
> +	/*
> +	 * Create the string if does not exist.
> +	 */
> +	if(st =3D=3D NULL) {
> +		st =3D (BIT_STRING_t *)(*sptr =3D CALLOC(1,
> specs->struct_size));
> +		if(st =3D=3D NULL) RETURN(RC_FAIL);
> +	}
> +
> +	/* Restore parsing context */
> +	ctx =3D (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
> +
> +	switch(ctx->phase) {
> +	case 0:
> +		/*
> +		 * Check tags.
> +		 */
> +		rval =3D ber_check_tags(opt_codec_ctx, td, ctx,
> +			buf_ptr, size, tag_mode, -1,
> +			&ctx->left, &tlv_constr);
> +		if(rval.code !=3D RC_OK)
> +			return rval;
> +
> +		if(tlv_constr) {
> +			/*
> +			 * Complex operation, requires stack of
> expectations.
> +			 */
> +			ctx->ptr =3D _new_stack();
> +			if(ctx->ptr) {
> +				stck =3D (struct _stack *)ctx->ptr;
> +			} else {
> +				RETURN(RC_FAIL);
> +			}
> +		} else {
> +			/*
> +			 * Jump into stackless primitive decoding.
> +			 */
> +			_CH_PHASE(ctx, 3);
> +			if(type_variant =3D=3D ASN_OSUBV_ANY &&
> tag_mode !=3D 1)
> +				APPEND(buf_ptr, rval.consumed);
> +			ADVANCE(rval.consumed);
> +			goto phase3;
> +		}
> +
> +		NEXT_PHASE(ctx);
> +		/* Fall through */
> +	case 1:
> +	phase1:
> +		/*
> +		 * Fill the stack with expectations.
> +		 */
> +		stck =3D (struct _stack *)ctx->ptr;
> +		sel =3D stck->cur_ptr;
> +	  do {
> +		ber_tlv_tag_t tlv_tag;
> +		ber_tlv_len_t tlv_len;
> +		ber_tlv_tag_t expected_tag;
> +		ssize_t tl, ll, tlvl;
> +				/* This one works even if (sel->left
> =3D=3D -1) */
> +		ssize_t Left =3D ((!sel||(size_t)sel->left >=3D size)
> +					?(ssize_t)size:sel->left);
> +
> +
> +		ASN_DEBUG("%p, s->l=3D%ld, s->wn=3D%ld, s->g=3D%ld\n", sel,
> +			(long)(sel?sel->left:0),
> +			(long)(sel?sel->want_nulls:0),
> +			(long)(sel?sel->got:0)
> +		);
> +		if(sel && sel->left <=3D 0 && sel->want_nulls =3D=3D 0) {
> +			if(sel->prev) {
> +				struct _stack_el *prev =3D sel->prev;
> +				if(prev->left !=3D -1) {
> +					if(prev->left < sel->got)
> +						RETURN(RC_FAIL);
> +					prev->left -=3D sel->got;
> +				}
> +				prev->got +=3D sel->got;
> +				sel =3D stck->cur_ptr =3D prev;
> +				if(!sel) break;
> +				tlv_constr =3D 1;
> +				continue;
> +			} else {
> +				sel =3D stck->cur_ptr =3D 0;
> +				break;	/* Nothing to wait */
> +			}
> +		}
> +
> +		tl =3D ber_fetch_tag(buf_ptr, Left, &tlv_tag);
> +		ASN_DEBUG("fetch tag(size=3D%ld,L=3D%ld), %sstack,
> left=3D%ld, wn=3D%ld, tl=3D%ld",
> +			(long)size, (long)Left, sel?"":"!",
> +			(long)(sel?sel->left:0),
> +			(long)(sel?sel->want_nulls:0),
> +			(long)tl);
> +		switch(tl) {
> +		case -1: RETURN(RC_FAIL);
> +		case 0: RETURN(RC_WMORE);
> +		}
> +
> +		tlv_constr =3D BER_TLV_CONSTRUCTED(buf_ptr);
> +
> +		ll =3D ber_fetch_length(tlv_constr,
> +				(const char *)buf_ptr + tl,Left -
> tl,&tlv_len);
> +		ASN_DEBUG("Got tag=3D%s, tc=3D%d, left=3D%ld, tl=3D%ld,
> len=3D%ld, ll=3D%ld",
> +			ber_tlv_tag_string(tlv_tag), tlv_constr,
> +				(long)Left, (long)tl, (long)tlv_len,
> (long)ll);
> +		switch(ll) {
> +		case -1: RETURN(RC_FAIL);
> +		case 0: RETURN(RC_WMORE);
> +		}
> +
> +		if(sel && sel->want_nulls
> +			&& ((const uint8_t *)buf_ptr)[0] =3D=3D 0
> +			&& ((const uint8_t *)buf_ptr)[1] =3D=3D 0)
> +		{
> +
> +			ASN_DEBUG("Eat EOC; wn=3D%d--",
> sel->want_nulls); +
> +			if(type_variant =3D=3D ASN_OSUBV_ANY
> +			&& (tag_mode !=3D 1 || sel->cont_level))
> +				APPEND("\0\0", 2);
> +
> +			ADVANCE(2);
> +			sel->got +=3D 2;
> +			if(sel->left !=3D -1) {
> +				sel->left -=3D 2;	/*
> assert(sel->left >=3D 2) */
> +			}
> +
> +			sel->want_nulls--;
> +			if(sel->want_nulls =3D=3D 0) {
> +				/* Move to the next expectation */
> +				sel->left =3D 0;
> +				tlv_constr =3D 1;
> +			}
> +
> +			continue;
> +		}
> +
> +		/*
> +		 * Set up expected tags,
> +		 * depending on ASN.1 type being decoded.
> +		 */
> +		switch(type_variant) {
> +		case ASN_OSUBV_BIT:
> +			/* X.690: 8.6.4.1, NOTE 2 */
> +			/* Fall through */
> +		case ASN_OSUBV_STR:
> +		default:
> +			if(sel) {
> +				int level =3D sel->cont_level;
> +				if(level < td->all_tags_count) {
> +					expected_tag =3D
> td->all_tags[level];
> +					break;
> +				} else if(td->all_tags_count) {
> +					expected_tag =3D td->all_tags
> +						[td->all_tags_count
> - 1];
> +					break;
> +				}
> +				/* else, Fall through */
> +			}
> +			/* Fall through */
> +		case ASN_OSUBV_ANY:
> +			expected_tag =3D tlv_tag;
> +			break;
> +		}
> +
> +
> +		if(tlv_tag !=3D expected_tag) {
> +			char buf[2][32];
> +			ber_tlv_tag_snprint(tlv_tag,
> +				buf[0], sizeof(buf[0]));
> +
> ber_tlv_tag_snprint(td->tags[td->tags_count-1],
> +				buf[1], sizeof(buf[1]));
> +			ASN_DEBUG("Tag does not match expectation:
> %s !=3D %s",
> +				buf[0], buf[1]);
> +			RETURN(RC_FAIL);
> +		}
> +
> +		tlvl =3D tl + ll;	/* Combined length of T and L
> encoding */
> +		if((tlv_len + tlvl) < 0) {
> +			/* tlv_len value is too big */
> +			ASN_DEBUG("TLV encoding + length (%ld) is
> too big",
> +				(long)tlv_len);
> +			RETURN(RC_FAIL);
> +		}
> +
> +		/*
> +		 * Append a new expectation.
> +		 */
> +		sel =3D OS__add_stack_el(stck);
> +		if(!sel) RETURN(RC_FAIL);
> +
> +		sel->tag =3D tlv_tag;
> +
> +		sel->want_nulls =3D (tlv_len=3D=3D-1);
> +		if(sel->prev && sel->prev->left !=3D -1) {
> +			/* Check that the parent frame is big enough
> */
> +			if(sel->prev->left < tlvl +
> (tlv_len=3D=3D-1?0:tlv_len))
> +				RETURN(RC_FAIL);
> +			if(tlv_len =3D=3D -1)
> +				sel->left =3D sel->prev->left - tlvl;
> +			else
> +				sel->left =3D tlv_len;
> +		} else {
> +			sel->left =3D tlv_len;
> +		}
> +		if(type_variant =3D=3D ASN_OSUBV_ANY
> +		&& (tag_mode !=3D 1 || sel->cont_level))
> +			APPEND(buf_ptr, tlvl);
> +		sel->got +=3D tlvl;
> +		ADVANCE(tlvl);
> +
> +		ASN_DEBUG("+EXPECT2 got=3D%ld left=3D%ld, wn=3D%d,
> clvl=3D%d",
> +			(long)sel->got, (long)sel->left,
> +			sel->want_nulls, sel->cont_level);
> +
> +	  } while(tlv_constr);
> +		if(sel =3D=3D NULL) {
> +			/* Finished operation, "phase out" */
> +			ASN_DEBUG("Phase out");
> +			_CH_PHASE(ctx, +3);
> +			break;
> +		}
> +
> +		NEXT_PHASE(ctx);
> +		/* Fall through */
> +	case 2:
> +		stck =3D (struct _stack *)ctx->ptr;
> +		sel =3D stck->cur_ptr;
> +		ASN_DEBUG("Phase 2: Need %ld bytes, size=3D%ld,
> alrg=3D%ld, wn=3D%d",
> +			(long)sel->left, (long)size, (long)sel->got,
> +				sel->want_nulls);
> +	    {
> +		ber_tlv_len_t len;
> +
> +		assert(sel->left >=3D 0);
> +
> +		len =3D ((ber_tlv_len_t)size < sel->left)
> +				? (ber_tlv_len_t)size : sel->left;
> +		if(len > 0) {
> +			if(type_variant =3D=3D ASN_OSUBV_BIT
> +			&& sel->bits_chopped =3D=3D 0) {
> +				/* Put the unused-bits-octet away */
> +				st->bits_unused =3D *(const uint8_t
> *)buf_ptr;
> +				APPEND(((const char *)buf_ptr+1),
> (len - 1));
> +				sel->bits_chopped =3D 1;
> +			} else {
> +				APPEND(buf_ptr, len);
> +			}
> +			ADVANCE(len);
> +			sel->left -=3D len;
> +			sel->got +=3D len;
> +		}
> +
> +		if(sel->left) {
> +			ASN_DEBUG("OS left %ld, size =3D %ld, wn=3D%d\n",
> +				(long)sel->left, (long)size,
> sel->want_nulls);
> +			RETURN(RC_WMORE);
> +		}
> +
> +		PREV_PHASE(ctx);
> +		goto phase1;
> +	    }
> +		break;
> +	case 3:
> +	phase3:
> +		/*
> +		 * Primitive form, no stack required.
> +		 */
> +		assert(ctx->left >=3D 0);
> +
> +		if(size < (size_t)ctx->left) {
> +			if(!size) RETURN(RC_WMORE);
> +			if(type_variant =3D=3D ASN_OSUBV_BIT
> && !ctx->context) {
> +				st->bits_unused =3D *(const uint8_t
> *)buf_ptr;
> +				ctx->left--;
> +				ADVANCE(1);
> +			}
> +			APPEND(buf_ptr, size);
> +			assert(ctx->context > 0);
> +			ctx->left -=3D size;
> +			ADVANCE(size);
> +			RETURN(RC_WMORE);
> +		} else {
> +			if(type_variant =3D=3D ASN_OSUBV_BIT
> +			&& !ctx->context && ctx->left) {
> +				st->bits_unused =3D *(const uint8_t
> *)buf_ptr;
> +				ctx->left--;
> +				ADVANCE(1);
> +			}
> +			APPEND(buf_ptr, ctx->left);
> +			ADVANCE(ctx->left);
> +			ctx->left =3D 0;
> +
> +			NEXT_PHASE(ctx);
> +		}
> +		break;
> +	}
> +
> +	if(sel) {
> +		ASN_DEBUG("3sel p=3D%p, wn=3D%d, l=3D%ld, g=3D%ld, size=3D%ld",
> +			sel->prev, sel->want_nulls,
> +			(long)sel->left, (long)sel->got, (long)size);
> +		if(sel->prev || sel->want_nulls > 1 || sel->left >
> 0) {
> +			RETURN(RC_WMORE);
> +		}
> +	}
> +
> +	/*
> +	 * BIT STRING-specific processing.
> +	 */
> +	if(type_variant =3D=3D ASN_OSUBV_BIT && st->size) {
> +		/* Finalize BIT STRING: zero out unused bits. */
> +		st->buf[st->size-1] &=3D 0xff << st->bits_unused;
> +	}
> +
> +	ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
> +		(long)consumed_myself, td->name,
> +		(type_variant =3D=3D ASN_OSUBV_STR) ? (char *)st->buf :
> "<data>",
> +		(long)st->size);
> +
> +
> +	RETURN(RC_OK);
> +}
> +
> +/*
> + * Encode OCTET STRING type using DER.
> + */
> +asn_enc_rval_t
> +OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
> +	int tag_mode, ber_tlv_tag_t tag,
> +	asn_app_consume_bytes_f *cb, void *app_key) {
> +	asn_enc_rval_t er;
> +	asn_OCTET_STRING_specifics_t *specs =3D td->specifics
> +				? (asn_OCTET_STRING_specifics_t
> *)td->specifics
> +				: &asn_DEF_OCTET_STRING_specs;
> +	BIT_STRING_t *st =3D (BIT_STRING_t *)sptr;
> +	enum asn_OS_Subvariant type_variant =3D specs->subvariant;
> +	int fix_last_byte =3D 0;
> +
> +	ASN_DEBUG("%s %s as OCTET STRING",
> +		cb?"Estimating":"Encoding", td->name);
> +
> +	/*
> +	 * Write tags.
> +	 */
> +	if(type_variant !=3D ASN_OSUBV_ANY || tag_mode =3D=3D 1) {
> +		er.encoded =3D der_write_tags(td,
> +				(type_variant =3D=3D ASN_OSUBV_BIT) +
> st->size,
> +			tag_mode, type_variant =3D=3D ASN_OSUBV_ANY, tag,
> +			cb, app_key);
> +		if(er.encoded =3D=3D -1) {
> +			er.failed_type =3D td;
> +			er.structure_ptr =3D sptr;
> +			return er;
> +		}
> +	} else {
> +		/* Disallow: [<tag>] IMPLICIT ANY */
> +		assert(type_variant !=3D ASN_OSUBV_ANY || tag_mode !=3D
> -1);
> +		er.encoded =3D 0;
> +	}
> +
> +	if(!cb) {
> +		er.encoded +=3D (type_variant =3D=3D ASN_OSUBV_BIT) +
> st->size;
> +		ASN__ENCODED_OK(er);
> +	}
> +
> +	/*
> +	 * Prepare to deal with the last octet of BIT STRING.
> +	 */
> +	if(type_variant =3D=3D ASN_OSUBV_BIT) {
> +		uint8_t b =3D st->bits_unused & 0x07;
> +		if(b && st->size) fix_last_byte =3D 1;
> +		ASN__CALLBACK(&b, 1);
> +		er.encoded++;
> +	}
> +
> +	/* Invoke callback for the main part of the buffer */
> +	ASN__CALLBACK(st->buf, st->size - fix_last_byte);
> +
> +	/* The last octet should be stripped off the unused bits */
> +	if(fix_last_byte) {
> +		uint8_t b =3D st->buf[st->size-1] & (0xff <<
> st->bits_unused);
> +		ASN__CALLBACK(&b, 1);
> +	}
> +
> +	er.encoded +=3D st->size;
> +	ASN__ENCODED_OK(er);
> +cb_failed:
> +	ASN__ENCODE_FAILED;
> +}
> +
> +asn_enc_rval_t
> +OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
> +	int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	const char * const h2c =3D "0123456789ABCDEF";
> +	const OCTET_STRING_t *st =3D (const OCTET_STRING_t *)sptr;
> +	asn_enc_rval_t er;
> +	char scratch[16 * 3 + 4];
> +	char *p =3D scratch;
> +	uint8_t *buf;
> +	uint8_t *end;
> +	size_t i;
> +
> +	if(!st || (!st->buf && st->size))
> +		ASN__ENCODE_FAILED;
> +
> +	er.encoded =3D 0;
> +
> +	/*
> +	 * Dump the contents of the buffer in hexadecimal.
> +	 */
> +	buf =3D st->buf;
> +	end =3D buf + st->size;
> +	if(flags & XER_F_CANONICAL) {
> +		char *scend =3D scratch + (sizeof(scratch) - 2);
> +		for(; buf < end; buf++) {
> +			if(p >=3D scend) {
> +				ASN__CALLBACK(scratch, p - scratch);
> +				er.encoded +=3D p - scratch;
> +				p =3D scratch;
> +			}
> +			*p++ =3D h2c[(*buf >> 4) & 0x0F];
> +			*p++ =3D h2c[*buf & 0x0F];
> +		}
> +
> +		ASN__CALLBACK(scratch, p-scratch);	/* Dump
> the rest */
> +		er.encoded +=3D p - scratch;
> +	} else {
> +		for(i =3D 0; buf < end; buf++, i++) {
> +			if(!(i % 16) && (i || st->size > 16)) {
> +				ASN__CALLBACK(scratch, p-scratch);
> +				er.encoded +=3D (p-scratch);
> +				p =3D scratch;
> +				ASN__TEXT_INDENT(1, ilevel);
> +			}
> +			*p++ =3D h2c[(*buf >> 4) & 0x0F];
> +			*p++ =3D h2c[*buf & 0x0F];
> +			*p++ =3D 0x20;
> +		}
> +		if(p - scratch) {
> +			p--;	/* Remove the tail space */
> +			ASN__CALLBACK(scratch, p-scratch); /* Dump
> the rest */
> +			er.encoded +=3D p - scratch;
> +			if(st->size > 16)
> +				ASN__TEXT_INDENT(1, ilevel-1);
> +		}
> +	}
> +
> +	ASN__ENCODED_OK(er);
> +cb_failed:
> +	ASN__ENCODE_FAILED;
> +}
> +
> +static const struct OCTET_STRING__xer_escape_table_s {
> +	const char *string;
> +	int size;
> +} OCTET_STRING__xer_escape_table[] =3D {
> +#define	OSXET(s)	{ s, sizeof(s) - 1 }
> +	OSXET("\074\156\165\154\057\076"),	/* <nul/> */
> +	OSXET("\074\163\157\150\057\076"),	/* <soh/> */
> +	OSXET("\074\163\164\170\057\076"),	/* <stx/> */
> +	OSXET("\074\145\164\170\057\076"),	/* <etx/> */
> +	OSXET("\074\145\157\164\057\076"),	/* <eot/> */
> +	OSXET("\074\145\156\161\057\076"),	/* <enq/> */
> +	OSXET("\074\141\143\153\057\076"),	/* <ack/> */
> +	OSXET("\074\142\145\154\057\076"),	/* <bel/> */
> +	OSXET("\074\142\163\057\076"),		/* <bs/> */
> +	OSXET("\011"),				/* \t */
> +	OSXET("\012"),				/* \n */
> +	OSXET("\074\166\164\057\076"),		/* <vt/> */
> +	OSXET("\074\146\146\057\076"),		/* <ff/> */
> +	OSXET("\015"),				/* \r */
> +	OSXET("\074\163\157\057\076"),		/* <so/> */
> +	OSXET("\074\163\151\057\076"),		/* <si/> */
> +	OSXET("\074\144\154\145\057\076"),	/* <dle/> */
> +	OSXET("\074\144\143\061\057\076"),	/* <de1/> */
> +	OSXET("\074\144\143\062\057\076"),	/* <de2/> */
> +	OSXET("\074\144\143\063\057\076"),	/* <de3/> */
> +	OSXET("\074\144\143\064\057\076"),	/* <de4/> */
> +	OSXET("\074\156\141\153\057\076"),	/* <nak/> */
> +	OSXET("\074\163\171\156\057\076"),	/* <syn/> */
> +	OSXET("\074\145\164\142\057\076"),	/* <etb/> */
> +	OSXET("\074\143\141\156\057\076"),	/* <can/> */
> +	OSXET("\074\145\155\057\076"),		/* <em/> */
> +	OSXET("\074\163\165\142\057\076"),	/* <sub/> */
> +	OSXET("\074\145\163\143\057\076"),	/* <esc/> */
> +	OSXET("\074\151\163\064\057\076"),	/* <is4/> */
> +	OSXET("\074\151\163\063\057\076"),	/* <is3/> */
> +	OSXET("\074\151\163\062\057\076"),	/* <is2/> */
> +	OSXET("\074\151\163\061\057\076"),	/* <is1/> */
> +	{ 0, 0 },	/* " " */
> +	{ 0, 0 },	/* ! */
> +	{ 0, 0 },	/* \" */
> +	{ 0, 0 },	/* # */
> +	{ 0, 0 },	/* $ */
> +	{ 0, 0 },	/* % */
> +	OSXET("\046\141\155\160\073"),	/* &amp; */
> +	{ 0, 0 },	/* ' */
> +	{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* ()*+,-./
> */
> +	{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* 01234567
> */
> +	{0,0},{0,0},{0,0},{0,0},			 /* 89:; */
> +	OSXET("\046\154\164\073"),	/* &lt; */
> +	{ 0, 0 },	/* =3D */
> +	OSXET("\046\147\164\073"),	/* &gt; */
> +};
> +
> +static int
> +OS__check_escaped_control_char(const void *buf, int size) {
> +	size_t i;
> +	/*
> +	 * Inefficient algorithm which translates the escape
> sequences
> +	 * defined above into characters. Returns -1 if not found.
> +	 * TODO: replace by a faster algorithm (bsearch(), hash or
> +	 * nested table lookups).
> +	 */
> +	for(i =3D 0; i < 32 /* Don't spend time on the bottom half */;
> i++) {
> +		const struct OCTET_STRING__xer_escape_table_s *el;
> +		el =3D &OCTET_STRING__xer_escape_table[i];
> +		if(el->size =3D=3D size && memcmp(buf, el->string, size)
> =3D=3D 0)
> +			return i;
> +	}
> +	return -1;
> +}
> +
> +static int
> +OCTET_STRING__handle_control_chars(void *struct_ptr, const void
> *chunk_buf, size_t chunk_size) {
> +	/*
> +	 * This might be one of the escape sequences
> +	 * for control characters. Check it out.
> +	 * #11.15.5
> +	 */
> +	int control_char =3D
> OS__check_escaped_control_char(chunk_buf,chunk_size);
> +	if(control_char >=3D 0) {
> +		OCTET_STRING_t *st =3D (OCTET_STRING_t *)struct_ptr;
> +		void *p =3D REALLOC(st->buf, st->size + 2);
> +		if(p) {
> +			st->buf =3D (uint8_t *)p;
> +			st->buf[st->size++] =3D control_char;
> +			st->buf[st->size] =3D '\0';	/*
> nul-termination */
> +			return 0;
> +		}
> +	}
> +=09
> +	return -1;	/* No, it's not */
> +}
> +
> +asn_enc_rval_t
> +OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr,
> +	int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	const OCTET_STRING_t *st =3D (const OCTET_STRING_t *)sptr;
> +	asn_enc_rval_t er;
> +	uint8_t *buf, *end;
> +	uint8_t *ss;	/* Sequence start */
> +	ssize_t encoded_len =3D 0;
> +
> +	(void)ilevel;	/* Unused argument */
> +	(void)flags;	/* Unused argument */
> +
> +	if(!st || (!st->buf && st->size))
> +		ASN__ENCODE_FAILED;
> +
> +	buf =3D st->buf;
> +	end =3D buf + st->size;
> +	for(ss =3D buf; buf < end; buf++) {
> +		unsigned int ch =3D *buf;
> +		int s_len;	/* Special encoding sequence
> length */ +
> +		/*
> +		 * Escape certain characters: X.680/11.15
> +		 */
> +		if(ch < sizeof(OCTET_STRING__xer_escape_table)
> +			/sizeof(OCTET_STRING__xer_escape_table[0])
> +		&& (s_len =3D
> OCTET_STRING__xer_escape_table[ch].size)) {
> +			if(((buf - ss) && cb(ss, buf - ss, app_key)
> < 0)
> +			||
> cb(OCTET_STRING__xer_escape_table[ch].string, s_len,
> +					app_key) < 0)
> +				ASN__ENCODE_FAILED;
> +			encoded_len +=3D (buf - ss) + s_len;
> +			ss =3D buf + 1;
> +		}
> +	}
> +
> +	encoded_len +=3D (buf - ss);
> +	if((buf - ss) && cb(ss, buf - ss, app_key) < 0)
> +		ASN__ENCODE_FAILED;
> +
> +	er.encoded =3D encoded_len;
> +	ASN__ENCODED_OK(er);
> +}
> +
> +/*
> + * Convert from hexadecimal format (cstring): "AB CD EF"
> + */
> +static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, const
> void *chunk_buf, size_t chunk_size, int have_more) {
> +	OCTET_STRING_t *st =3D (OCTET_STRING_t *)sptr;
> +	const char *chunk_stop =3D (const char *)chunk_buf;
> +	const char *p =3D chunk_stop;
> +	const char *pend =3D p + chunk_size;
> +	unsigned int clv =3D 0;
> +	int half =3D 0;	/* Half bit */
> +	uint8_t *buf;
> +
> +	/* Reallocate buffer according to high cap estimation */
> +	ssize_t _ns =3D st->size + (chunk_size + 1) / 2;
> +	void *nptr =3D REALLOC(st->buf, _ns + 1);
> +	if(!nptr) return -1;
> +	st->buf =3D (uint8_t *)nptr;
> +	buf =3D st->buf + st->size;
> +
> +	/*
> +	 * If something like " a b c " appears here, the " a b":3
> will be
> +	 * converted, and the rest skipped. That is, unless buf_size
> is greater
> +	 * than chunk_size, then it'll be equivalent to "ABC0".
> +	 */
> +	for(; p < pend; p++) {
> +		int ch =3D *(const unsigned char *)p;
> +		switch(ch) {
> +		case 0x09: case 0x0a: case 0x0c: case 0x0d:
> +		case 0x20:
> +			/* Ignore whitespace */
> +			continue;
> +		case 0x30: case 0x31: case 0x32: case 0x33: case
> 0x34: /*01234*/
> +		case 0x35: case 0x36: case 0x37: case 0x38: case
> 0x39: /*56789*/
> +			clv =3D (clv << 4) + (ch - 0x30);
> +			break;
> +		case 0x41: case 0x42: case 0x43:	/* ABC */
> +		case 0x44: case 0x45: case 0x46:	/* DEF */
> +			clv =3D (clv << 4) + (ch - 0x41 + 10);
> +			break;
> +		case 0x61: case 0x62: case 0x63:	/* abc */
> +		case 0x64: case 0x65: case 0x66:	/* def */
> +			clv =3D (clv << 4) + (ch - 0x61 + 10);
> +			break;
> +		default:
> +			*buf =3D 0;	/* JIC */
> +			return -1;
> +		}
> +		if(half++) {
> +			half =3D 0;
> +			*buf++ =3D clv;
> +			chunk_stop =3D p + 1;
> +		}
> +	}
> +
> +	/*
> +	 * Check partial decoding.
> +	 */
> +	if(half) {
> +		if(have_more) {
> +			/*
> +			 * Partial specification is fine,
> +			 * because no more more PXER_TEXT data is
> available.
> +			 */
> +			*buf++ =3D clv << 4;
> +			chunk_stop =3D p;
> +		}
> +	} else {
> +		chunk_stop =3D p;
> +	}
> +
> +	st->size =3D buf - st->buf;	/* Adjust the buffer size */
> +	assert(st->size <=3D _ns);
> +	st->buf[st->size] =3D 0;		/* Courtesy
> termination */ +
> +	return (chunk_stop - (const char *)chunk_buf);	/*
> Converted size */ +}
> +
> +/*
> + * Convert from binary format: "00101011101"
> + */
> +static ssize_t OCTET_STRING__convert_binary(void *sptr, const void
> *chunk_buf, size_t chunk_size, int have_more) {
> +	BIT_STRING_t *st =3D (BIT_STRING_t *)sptr;
> +	const char *p =3D (const char *)chunk_buf;
> +	const char *pend =3D p + chunk_size;
> +	int bits_unused =3D st->bits_unused & 0x7;
> +	uint8_t *buf;
> +
> +	/* Reallocate buffer according to high cap estimation */
> +	ssize_t _ns =3D st->size + (chunk_size + 7) / 8;
> +	void *nptr =3D REALLOC(st->buf, _ns + 1);
> +	if(!nptr) return -1;
> +	st->buf =3D (uint8_t *)nptr;
> +	buf =3D st->buf + st->size;
> +
> +	(void)have_more;
> +
> +	if(bits_unused =3D=3D 0)
> +		bits_unused =3D 8;
> +	else if(st->size)
> +		buf--;
> +
> +	/*
> +	 * Convert series of 0 and 1 into the octet string.
> +	 */
> +	for(; p < pend; p++) {
> +		int ch =3D *(const unsigned char *)p;
> +		switch(ch) {
> +		case 0x09: case 0x0a: case 0x0c: case 0x0d:
> +		case 0x20:
> +			/* Ignore whitespace */
> +			break;
> +		case 0x30:
> +		case 0x31:
> +			if(bits_unused-- <=3D 0) {
> +				*++buf =3D 0;	/* Clean the cell
> */
> +				bits_unused =3D 7;
> +			}
> +			*buf |=3D (ch&1) << bits_unused;
> +			break;
> +		default:
> +			st->bits_unused =3D bits_unused;
> +			return -1;
> +		}
> +	}
> +
> +	if(bits_unused =3D=3D 8) {
> +		st->size =3D buf - st->buf;
> +		st->bits_unused =3D 0;
> +	} else {
> +		st->size =3D buf - st->buf + 1;
> +		st->bits_unused =3D bits_unused;
> +	}
> +
> +	assert(st->size <=3D _ns);
> +	st->buf[st->size] =3D 0;		/* Courtesy
> termination */ +
> +	return chunk_size;	/* Converted in full */
> +}
> +
> +/*
> + * Something like strtod(), but with stricter rules.
> + */
> +static int
> +OS__strtoent(int base, const char *buf, const char *end, int32_t
> *ret_value) {
> +	int32_t val =3D 0;
> +	const char *p;
> +
> +	for(p =3D buf; p < end; p++) {
> +		int ch =3D *p;
> +
> +		/* Strange huge value */
> +		if((val * base + base) < 0)
> +			return -1;
> +
> +		switch(ch) {
> +		case 0x30: case 0x31: case 0x32: case 0x33: case
> 0x34: /*01234*/
> +		case 0x35: case 0x36: case 0x37: case 0x38: case
> 0x39: /*56789*/
> +			val =3D val * base + (ch - 0x30);
> +			break;
> +		case 0x41: case 0x42: case 0x43:	/* ABC */
> +		case 0x44: case 0x45: case 0x46:	/* DEF */
> +			val =3D val * base + (ch - 0x41 + 10);
> +			break;
> +		case 0x61: case 0x62: case 0x63:	/* abc */
> +		case 0x64: case 0x65: case 0x66:	/* def */
> +			val =3D val * base + (ch - 0x61 + 10);
> +			break;
> +		case 0x3b:	/* ';' */
> +			*ret_value =3D val;
> +			return (p - buf) + 1;
> +		default:
> +			return -1;	/* Character set error */
> +		}
> +	}
> +
> +	*ret_value =3D -1;
> +	return (p - buf);
> +}
> +
> +/*
> + * Convert from the plain UTF-8 format, expanding entity references:
> "2 &lt; 3"
> + */
> +static ssize_t OCTET_STRING__convert_entrefs(void *sptr, const void
> *chunk_buf, size_t chunk_size, int have_more) {
> +	OCTET_STRING_t *st =3D (OCTET_STRING_t *)sptr;
> +	const char *p =3D (const char *)chunk_buf;
> +	const char *pend =3D p + chunk_size;
> +	uint8_t *buf;
> +
> +	/* Reallocate buffer */
> +	ssize_t _ns =3D st->size + chunk_size;
> +	void *nptr =3D REALLOC(st->buf, _ns + 1);
> +	if(!nptr) return -1;
> +	st->buf =3D (uint8_t *)nptr;
> +	buf =3D st->buf + st->size;
> +
> +	/*
> +	 * Convert series of 0 and 1 into the octet string.
> +	 */
> +	for(; p < pend; p++) {
> +		int ch =3D *(const unsigned char *)p;
> +		int len;	/* Length of the rest of the chunk */
> +
> +		if(ch !=3D 0x26 /* '&' */) {
> +			*buf++ =3D ch;
> +			continue;	/* That was easy... */
> +		}
> +
> +		/*
> +		 * Process entity reference.
> +		 */
> +		len =3D chunk_size - (p - (const char *)chunk_buf);
> +		if(len =3D=3D 1 /* "&" */) goto want_more;
> +		if(p[1] =3D=3D 0x23 /* '#' */) {
> +			const char *pval;	/* Pointer to start
> of digits */
> +			int32_t val =3D 0;	/* Entity reference
> value */
> +			int base;
> +
> +			if(len =3D=3D 2 /* "&#" */) goto want_more;
> +			if(p[2] =3D=3D 0x78 /* 'x' */)
> +				pval =3D p + 3, base =3D 16;
> +			else
> +				pval =3D p + 2, base =3D 10;
> +			len =3D OS__strtoent(base, pval, p + len,
> &val);
> +			if(len =3D=3D -1) {
> +				/* Invalid charset. Just copy
> verbatim. */
> +				*buf++ =3D ch;
> +				continue;
> +			}
> +			if(!len || pval[len-1] !=3D 0x3b) goto
> want_more;
> +			assert(val > 0);
> +			p +=3D (pval - p) + len - 1; /* Advance past
> entref */ +
> +			if(val < 0x80) {
> +				*buf++ =3D (char)val;
> +			} else if(val < 0x800) {
> +				*buf++ =3D 0xc0 | ((val >> 6));
> +				*buf++ =3D 0x80 | ((val & 0x3f));
> +			} else if(val < 0x10000) {
> +				*buf++ =3D 0xe0 | ((val >> 12));
> +				*buf++ =3D 0x80 | ((val >> 6) & 0x3f);
> +				*buf++ =3D 0x80 | ((val & 0x3f));
> +			} else if(val < 0x200000) {
> +				*buf++ =3D 0xf0 | ((val >> 18));
> +				*buf++ =3D 0x80 | ((val >> 12) & 0x3f);
> +				*buf++ =3D 0x80 | ((val >> 6) & 0x3f);
> +				*buf++ =3D 0x80 | ((val & 0x3f));
> +			} else if(val < 0x4000000) {
> +				*buf++ =3D 0xf8 | ((val >> 24));
> +				*buf++ =3D 0x80 | ((val >> 18) & 0x3f);
> +				*buf++ =3D 0x80 | ((val >> 12) & 0x3f);
> +				*buf++ =3D 0x80 | ((val >> 6) & 0x3f);
> +				*buf++ =3D 0x80 | ((val & 0x3f));
> +			} else {
> +				*buf++ =3D 0xfc | ((val >> 30) & 0x1);
> +				*buf++ =3D 0x80 | ((val >> 24) & 0x3f);
> +				*buf++ =3D 0x80 | ((val >> 18) & 0x3f);
> +				*buf++ =3D 0x80 | ((val >> 12) & 0x3f);
> +				*buf++ =3D 0x80 | ((val >> 6) & 0x3f);
> +				*buf++ =3D 0x80 | ((val & 0x3f));
> +			}
> +		} else {
> +			/*
> +			 * Ugly, limited parsing of &amp; &gt; &lt;
> +			 */
> +			char *sc =3D (char *)memchr(p, 0x3b, len > 5 ?
> 5 : len);
> +			if(!sc) goto want_more;
> +			if((sc - p) =3D=3D 4
> +				&& p[1] =3D=3D 0x61	/* 'a' */
> +				&& p[2] =3D=3D 0x6d	/* 'm' */
> +				&& p[3] =3D=3D 0x70	/* 'p' */) {
> +				*buf++ =3D 0x26;
> +				p =3D sc;
> +				continue;
> +			}
> +			if((sc - p) =3D=3D 3) {
> +				if(p[1] =3D=3D 0x6c) {
> +					*buf =3D 0x3c;	/* '<' */
> +				} else if(p[1] =3D=3D 0x67) {
> +					*buf =3D 0x3e;	/* '>' */
> +				} else {
> +					/* Unsupported entity
> reference */
> +					*buf++ =3D ch;
> +					continue;
> +				}
> +				if(p[2] !=3D 0x74) {
> +					/* Unsupported entity
> reference */
> +					*buf++ =3D ch;
> +					continue;
> +				}
> +				buf++;
> +				p =3D sc;
> +				continue;
> +			}
> +			/* Unsupported entity reference */
> +			*buf++ =3D ch;
> +		}
> +
> +		continue;
> +	want_more:
> +		if(have_more) {
> +			/*
> +			 * We know that no more data (of the same
> type)
> +			 * is coming. Copy the rest verbatim.
> +			 */
> +			*buf++ =3D ch;
> +			continue;
> +		}
> +		chunk_size =3D (p - (const char *)chunk_buf);
> +		/* Processing stalled: need more data */
> +		break;
> +	}
> +
> +	st->size =3D buf - st->buf;
> +	assert(st->size <=3D _ns);
> +	st->buf[st->size] =3D 0;		/* Courtesy
> termination */ +
> +	return chunk_size;	/* Converted in full */
> +}
> +
> +/*
> + * Decode OCTET STRING from the XML element's body.
> + */
> +static asn_dec_rval_t
> +OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td, void **sptr,
> +	const char *opt_mname, const void *buf_ptr, size_t size,
> +	int (*opt_unexpected_tag_decoder)
> +		(void *struct_ptr, const void *chunk_buf, size_t
> chunk_size),
> +	ssize_t (*body_receiver)
> +		(void *struct_ptr, const void *chunk_buf, size_t
> chunk_size,
> +			int have_more)
> +) {
> +	OCTET_STRING_t *st =3D (OCTET_STRING_t *)*sptr;
> +	asn_OCTET_STRING_specifics_t *specs =3D td->specifics
> +				? (asn_OCTET_STRING_specifics_t
> *)td->specifics
> +				: &asn_DEF_OCTET_STRING_specs;
> +	const char *xml_tag =3D opt_mname ? opt_mname : td->xml_tag;
> +	asn_struct_ctx_t *ctx;		/* Per-structure
> parser context */
> +	asn_dec_rval_t rval;		/* Return value from the
> decoder */
> +	int st_allocated;
> +
> +	/*
> +	 * Create the string if does not exist.
> +	 */
> +	if(!st) {
> +		st =3D (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
> +		*sptr =3D (void *)st;
> +		if(!st) goto sta_failed;
> +		st_allocated =3D 1;
> +	} else {
> +		st_allocated =3D 0;
> +	}
> +	if(!st->buf) {
> +		/* This is separate from above section */
> +		st->buf =3D (uint8_t *)CALLOC(1, 1);
> +		if(!st->buf) {
> +			if(st_allocated) {
> +				*sptr =3D 0;
> +				goto stb_failed;
> +			} else {
> +				goto sta_failed;
> +			}
> +		}
> +	}
> +
> +	/* Restore parsing context */
> +	ctx =3D (asn_struct_ctx_t *)(((char *)*sptr) +
> specs->ctx_offset); +
> +	return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag,
> +		buf_ptr, size, opt_unexpected_tag_decoder,
> body_receiver); +
> +stb_failed:
> +	FREEMEM(st);
> +sta_failed:
> +	rval.code =3D RC_FAIL;
> +	rval.consumed =3D 0;
> +	return rval;
> +}
> +
> +/*
> + * Decode OCTET STRING from the hexadecimal data.
> + */
> +asn_dec_rval_t
> +OCTET_STRING_decode_xer_hex(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td, void **sptr,
> +		const char *opt_mname, const void *buf_ptr, size_t
> size) {
> +	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr,
> opt_mname,
> +		buf_ptr, size, 0, OCTET_STRING__convert_hexadecimal);
> +}
> +
> +/*
> + * Decode OCTET STRING from the binary (0/1) data.
> + */
> +asn_dec_rval_t
> +OCTET_STRING_decode_xer_binary(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td, void **sptr,
> +		const char *opt_mname, const void *buf_ptr, size_t
> size) {
> +	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr,
> opt_mname,
> +		buf_ptr, size, 0, OCTET_STRING__convert_binary);
> +}
> +
> +/*
> + * Decode OCTET STRING from the string (ASCII/UTF-8) data.
> + */
> +asn_dec_rval_t
> +OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td, void **sptr,
> +		const char *opt_mname, const void *buf_ptr, size_t
> size) {
> +	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr,
> opt_mname,
> +		buf_ptr, size,
> +		OCTET_STRING__handle_control_chars,
> +		OCTET_STRING__convert_entrefs);
> +}
> +
> +static int
> +OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
> +		size_t units, unsigned int bpc, unsigned int
> unit_bits,
> +		long lb, long ub, asn_per_constraints_t *pc) {
> +	uint8_t *end =3D buf + units * bpc;
> +
> +	ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d",
> +		(int)units, lb, ub, unit_bits);
> +
> +	/* X.691: 27.5.4 */
> +	if((unsigned long)ub <=3D ((unsigned long)2 << (unit_bits -
> 1))) {
> +		/* Decode without translation */
> +		lb =3D 0;
> +	} else if(pc && pc->code2value) {
> +		if(unit_bits > 16)
> +			return 1;	/* FATAL: can't have
> constrained
> +					 * UniversalString with more
> than
> +					 * 16 million code points */
> +		for(; buf < end; buf +=3D bpc) {
> +			int value;
> +			int code =3D per_get_few_bits(po, unit_bits);
> +			if(code < 0) return -1;	/* WMORE */
> +			value =3D pc->code2value(code);
> +			if(value < 0) {
> +				ASN_DEBUG("Code %d (0x%02x) is"
> +					" not in map (%ld..%ld)",
> +					code, code, lb, ub);
> +				return 1;	/* FATAL */
> +			}
> +			switch(bpc) {
> +			case 1: *buf =3D value; break;
> +			case 2: buf[0] =3D value >> 8; buf[1] =3D value;
> break;
> +			case 4: buf[0] =3D value >> 24; buf[1] =3D value
> >> 16;
> +				buf[2] =3D value >> 8; buf[3] =3D value;
> break;
> +			}
> +		}
> +		return 0;
> +	}
> +
> +	/* Shortcut the no-op copying to the aligned structure */
> +	if(lb =3D=3D 0 && (unit_bits =3D=3D 8 * bpc)) {
> +		return per_get_many_bits(po, buf, 0, unit_bits *
> units);
> +	}
> +
> +	for(; buf < end; buf +=3D bpc) {
> +		int code =3D per_get_few_bits(po, unit_bits);
> +		int ch =3D code + lb;
> +		if(code < 0) return -1;	/* WMORE */
> +		if(ch > ub) {
> +			ASN_DEBUG("Code %d is out of range
> (%ld..%ld)",
> +				ch, lb, ub);
> +			return 1;	/* FATAL */
> +		}
> +		switch(bpc) {
> +		case 1: *buf =3D ch; break;
> +		case 2: buf[0] =3D ch >> 8; buf[1] =3D ch; break;
> +		case 4: buf[0] =3D ch >> 24; buf[1] =3D ch >> 16;
> +			buf[2] =3D ch >> 8; buf[3] =3D ch; break;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t
> *buf,
> +		size_t units, unsigned int bpc, unsigned int
> unit_bits,
> +		long lb, long ub, asn_per_constraints_t *pc) {
> +	const uint8_t *end =3D buf + units * bpc;
> +
> +	ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d
> bpc)",
> +		(int)units, lb, ub, unit_bits, bpc);
> +
> +	/* X.691: 27.5.4 */
> +	if((unsigned long)ub <=3D ((unsigned long)2 << (unit_bits -
> 1))) {
> +		/* Encode as is */
> +		lb =3D 0;
> +	} else if(pc && pc->value2code) {
> +		for(; buf < end; buf +=3D bpc) {
> +			int code;
> +			uint32_t value;
> +			switch(bpc) {
> +			case 1: value =3D *(const uint8_t *)buf; break;
> +			case 2: value =3D (buf[0] << 8) | buf[1];
> break;
> +			case 4: value =3D (buf[0] << 24) | (buf[1] <<
> 16)
> +					| (buf[2] << 8) | buf[3];
> break;
> +			default: return -1;
> +			}
> +			code =3D pc->value2code(value);
> +			if(code < 0) {
> +				ASN_DEBUG("Character %d (0x%02x) is"
> +					" not in map (%ld..%ld)",
> +					*buf, *buf, lb, ub);
> +				return -1;
> +			}
> +			if(per_put_few_bits(po, code, unit_bits))
> +				return -1;
> +		}
> +	}
> +
> +	/* Shortcut the no-op copying to the aligned structure */
> +	if(lb =3D=3D 0 && (unit_bits =3D=3D 8 * bpc)) {
> +		return per_put_many_bits(po, buf, unit_bits * units);
> +	}
> +
> +	for(ub -=3D lb; buf < end; buf +=3D bpc) {
> +		int ch;
> +		uint32_t value;
> +		switch(bpc) {
> +		case 1: value =3D *(const uint8_t *)buf; break;
> +		case 2: value =3D (buf[0] << 8) | buf[1]; break;
> +		case 4: value =3D (buf[0] << 24) | (buf[1] << 16)
> +				| (buf[2] << 8) | buf[3]; break;
> +		default: return -1;
> +		}
> +		ch =3D value - lb;
> +		if(ch < 0 || ch > ub) {
> +			ASN_DEBUG("Character %d (0x%02x)"
> +			" is out of range (%ld..%ld)",
> +				*buf, *buf, lb, ub + lb);
> +			return -1;
> +		}
> +		if(per_put_few_bits(po, ch, unit_bits))
> +			return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +asn_dec_rval_t
> +OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td, asn_per_constraints_t
> *constraints,
> +	void **sptr, asn_per_data_t *pd) {
> +
> +	asn_OCTET_STRING_specifics_t *specs =3D td->specifics
> +		? (asn_OCTET_STRING_specifics_t *)td->specifics
> +		: &asn_DEF_OCTET_STRING_specs;
> +	asn_per_constraints_t *pc =3D constraints ? constraints
> +				: td->per_constraints;
> +	asn_per_constraint_t *cval;
> +	asn_per_constraint_t *csiz;
> +	asn_dec_rval_t rval =3D { RC_OK, 0 };
> +	BIT_STRING_t *st =3D (BIT_STRING_t *)*sptr;
> +	ssize_t consumed_myself =3D 0;
> +	int repeat;
> +	enum {
> +		OS__BPC_BIT	=3D 0,
> +		OS__BPC_CHAR	=3D 1,
> +		OS__BPC_U16	=3D 2,
> +		OS__BPC_U32	=3D 4
> +	} bpc;	/* Bytes per character */
> +	unsigned int unit_bits;
> +	unsigned int canonical_unit_bits;
> +
> +	(void)opt_codec_ctx;
> +
> +	if(pc) {
> +		cval =3D &pc->value;
> +		csiz =3D &pc->size;
> +	} else {
> +		cval =3D &asn_DEF_OCTET_STRING_constraints.value;
> +		csiz =3D &asn_DEF_OCTET_STRING_constraints.size;
> +	}
> +
> +	switch(specs->subvariant) {
> +	default:
> +	case ASN_OSUBV_ANY:
> +		ASN_DEBUG("Unrecognized subvariant %d",
> specs->subvariant);
> +		RETURN(RC_FAIL);
> +	case ASN_OSUBV_BIT:
> +		canonical_unit_bits =3D unit_bits =3D 1;
> +		bpc =3D OS__BPC_BIT;
> +		break;
> +	case ASN_OSUBV_STR:
> +		canonical_unit_bits =3D unit_bits =3D 8;
> +		if(cval->flags & APC_CONSTRAINED)
> +			unit_bits =3D cval->range_bits;
> +		bpc =3D OS__BPC_CHAR;
> +		break;
> +	case ASN_OSUBV_U16:
> +		canonical_unit_bits =3D unit_bits =3D 16;
> +		if(cval->flags & APC_CONSTRAINED)
> +			unit_bits =3D cval->range_bits;
> +		bpc =3D OS__BPC_U16;
> +		break;
> +	case ASN_OSUBV_U32:
> +		canonical_unit_bits =3D unit_bits =3D 32;
> +		if(cval->flags & APC_CONSTRAINED)
> +			unit_bits =3D cval->range_bits;
> +		bpc =3D OS__BPC_U32;
> +		break;
> +	}
> +
> +	/*
> +	 * Allocate the string.
> +	 */
> +	if(!st) {
> +		st =3D (BIT_STRING_t *)(*sptr =3D CALLOC(1,
> specs->struct_size));
> +		if(!st) RETURN(RC_FAIL);
> +	}
> +
> +	ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
> +		csiz->flags & APC_EXTENSIBLE ? "extensible" :
> "non-extensible",
> +		csiz->lower_bound, csiz->upper_bound,
> csiz->effective_bits); +
> +	if(csiz->flags & APC_EXTENSIBLE) {
> +		int inext =3D per_get_few_bits(pd, 1);
> +		if(inext < 0) RETURN(RC_WMORE);
> +		if(inext) {
> +			csiz =3D
> &asn_DEF_OCTET_STRING_constraints.size;
> +			cval =3D
> &asn_DEF_OCTET_STRING_constraints.value;
> +			unit_bits =3D canonical_unit_bits;
> +		}
> +	}
> +
> +	if(csiz->effective_bits >=3D 0) {
> +		FREEMEM(st->buf);
> +		if(bpc) {
> +			st->size =3D csiz->upper_bound * bpc;
> +		} else {
> +			st->size =3D (csiz->upper_bound + 7) >> 3;
> +		}
> +		st->buf =3D (uint8_t *)MALLOC(st->size + 1);
> +		if(!st->buf) { st->size =3D 0; RETURN(RC_FAIL); }
> +	}
> +
> +	/* X.691, #16.5: zero-length encoding */
> +	/* X.691, #16.6: short fixed length encoding (up to 2
> octets) */
> +	/* X.691, #16.7: long fixed length encoding (up to 64K
> octets) */
> +	if(csiz->effective_bits =3D=3D 0) {
> +		int ret;
> +		if(bpc) {
> +			ASN_DEBUG("Encoding OCTET STRING size %ld",
> +				csiz->upper_bound);
> +			ret =3D OCTET_STRING_per_get_characters(pd,
> st->buf,
> +				csiz->upper_bound, bpc, unit_bits,
> +				cval->lower_bound,
> cval->upper_bound, pc);
> +			if(ret > 0) RETURN(RC_FAIL);
> +		} else {
> +			ASN_DEBUG("Encoding BIT STRING size %ld",
> +				csiz->upper_bound);
> +			ret =3D per_get_many_bits(pd, st->buf, 0,
> +					    unit_bits *
> csiz->upper_bound);
> +		}
> +		if(ret < 0) RETURN(RC_WMORE);
> +		consumed_myself +=3D unit_bits * csiz->upper_bound;
> +		st->buf[st->size] =3D 0;
> +		if(bpc =3D=3D 0) {
> +			int ubs =3D (csiz->upper_bound & 0x7);
> +			st->bits_unused =3D ubs ? 8 - ubs : 0;
> +		}
> +		RETURN(RC_OK);
> +	}
> +
> +	st->size =3D 0;
> +	do {
> +		ssize_t raw_len;
> +		ssize_t len_bytes;
> +		ssize_t len_bits;
> +		void *p;
> +		int ret;
> +
> +		/* Get the PER length */
> +		raw_len =3D uper_get_length(pd, csiz->effective_bits,
> &repeat);
> +		if(raw_len < 0) RETURN(RC_WMORE);
> +		raw_len +=3D csiz->lower_bound;
> +
> +		ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
> +			(long)csiz->effective_bits, (long)raw_len,
> +			repeat ? "repeat" : "once", td->name);
> +		if(bpc) {
> +			len_bytes =3D raw_len * bpc;
> +			len_bits =3D len_bytes * unit_bits;
> +		} else {
> +			len_bits =3D raw_len;
> +			len_bytes =3D (len_bits + 7) >> 3;
> +			if(len_bits & 0x7)
> +				st->bits_unused =3D 8 - (len_bits &
> 0x7);
> +			/* len_bits be multiple of 16K if repeat is
> set */
> +		}
> +		p =3D REALLOC(st->buf, st->size + len_bytes + 1);
> +		if(!p) RETURN(RC_FAIL);
> +		st->buf =3D (uint8_t *)p;
> +
> +		if(bpc) {
> +			ret =3D OCTET_STRING_per_get_characters(pd,
> +				&st->buf[st->size], raw_len, bpc,
> unit_bits,
> +				cval->lower_bound,
> cval->upper_bound, pc);
> +			if(ret > 0) RETURN(RC_FAIL);
> +		} else {
> +			ret =3D per_get_many_bits(pd,
> &st->buf[st->size],
> +				0, len_bits);
> +		}
> +		if(ret < 0) RETURN(RC_WMORE);
> +		st->size +=3D len_bytes;
> +	} while(repeat);
> +	st->buf[st->size] =3D 0;	/* nul-terminate */
> +
> +	return rval;
> +}
> +
> +asn_enc_rval_t
> +OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
> +        asn_per_constraints_t *constraints, void *sptr,
> asn_per_outp_t *po) { +
> +	asn_OCTET_STRING_specifics_t *specs =3D td->specifics
> +		? (asn_OCTET_STRING_specifics_t *)td->specifics
> +		: &asn_DEF_OCTET_STRING_specs;
> +	asn_per_constraints_t *pc =3D constraints ? constraints
> +				: td->per_constraints;
> +	asn_per_constraint_t *cval;
> +	asn_per_constraint_t *csiz;
> +	const BIT_STRING_t *st =3D (const BIT_STRING_t *)sptr;
> +	asn_enc_rval_t er =3D { 0, 0, 0 };
> +	int inext =3D 0;		/* Lies not within extension
> root */
> +	unsigned int unit_bits;
> +	unsigned int canonical_unit_bits;
> +	unsigned int sizeinunits;
> +	const uint8_t *buf;
> +	int ret;
> +	enum {
> +		OS__BPC_BIT	=3D 0,
> +		OS__BPC_CHAR	=3D 1,
> +		OS__BPC_U16	=3D 2,
> +		OS__BPC_U32	=3D 4
> +	} bpc;	/* Bytes per character */
> +	int ct_extensible;
> +
> +	if(!st || (!st->buf && st->size))
> +		ASN__ENCODE_FAILED;
> +
> +	if(pc) {
> +		cval =3D &pc->value;
> +		csiz =3D &pc->size;
> +	} else {
> +		cval =3D &asn_DEF_OCTET_STRING_constraints.value;
> +		csiz =3D &asn_DEF_OCTET_STRING_constraints.size;
> +	}
> +	ct_extensible =3D csiz->flags & APC_EXTENSIBLE;
> +
> +	switch(specs->subvariant) {
> +	default:
> +	case ASN_OSUBV_ANY:
> +		ASN__ENCODE_FAILED;
> +	case ASN_OSUBV_BIT:
> +		canonical_unit_bits =3D unit_bits =3D 1;
> +		bpc =3D OS__BPC_BIT;
> +		sizeinunits =3D st->size * 8 - (st->bits_unused &
> 0x07);
> +		ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
> +				sizeinunits, st->bits_unused);
> +		break;
> +	case ASN_OSUBV_STR:
> +		canonical_unit_bits =3D unit_bits =3D 8;
> +		if(cval->flags & APC_CONSTRAINED)
> +			unit_bits =3D cval->range_bits;
> +		bpc =3D OS__BPC_CHAR;
> +		sizeinunits =3D st->size;
> +		break;
> +	case ASN_OSUBV_U16:
> +		canonical_unit_bits =3D unit_bits =3D 16;
> +		if(cval->flags & APC_CONSTRAINED)
> +			unit_bits =3D cval->range_bits;
> +		bpc =3D OS__BPC_U16;
> +		sizeinunits =3D st->size / 2;
> +		break;
> +	case ASN_OSUBV_U32:
> +		canonical_unit_bits =3D unit_bits =3D 32;
> +		if(cval->flags & APC_CONSTRAINED)
> +			unit_bits =3D cval->range_bits;
> +		bpc =3D OS__BPC_U32;
> +		sizeinunits =3D st->size / 4;
> +		break;
> +	}
> +
> +	ASN_DEBUG("Encoding %s into %d units of %d bits"
> +		" (%ld..%ld, effective %d)%s",
> +		td->name, sizeinunits, unit_bits,
> +		csiz->lower_bound, csiz->upper_bound,
> +		csiz->effective_bits, ct_extensible ? " EXT" : "");
> +
> +	/* Figure out whether size lies within PER visible
> constraint */ +
> +	if(csiz->effective_bits >=3D 0) {
> +		if((int)sizeinunits < csiz->lower_bound
> +		|| (int)sizeinunits > csiz->upper_bound) {
> +			if(ct_extensible) {
> +				cval =3D
> &asn_DEF_OCTET_STRING_constraints.value;
> +				csiz =3D
> &asn_DEF_OCTET_STRING_constraints.size;
> +				unit_bits =3D canonical_unit_bits;
> +				inext =3D 1;
> +			} else
> +				ASN__ENCODE_FAILED;
> +		}
> +	} else {
> +		inext =3D 0;
> +	}
> +
> +	if(ct_extensible) {
> +		/* Declare whether length is [not] within extension
> root */
> +		if(per_put_few_bits(po, inext, 1))
> +			ASN__ENCODE_FAILED;
> +	}
> +
> +	/* X.691, #16.5: zero-length encoding */
> +	/* X.691, #16.6: short fixed length encoding (up to 2
> octets) */
> +	/* X.691, #16.7: long fixed length encoding (up to 64K
> octets) */
> +	if(csiz->effective_bits >=3D 0) {
> +		ASN_DEBUG("Encoding %d bytes (%ld), length in %d
> bits",
> +				st->size, sizeinunits -
> csiz->lower_bound,
> +				csiz->effective_bits);
> +		ret =3D per_put_few_bits(po, sizeinunits -
> csiz->lower_bound,
> +				csiz->effective_bits);
> +		if(ret) ASN__ENCODE_FAILED;
> +		if(bpc) {
> +			ret =3D OCTET_STRING_per_put_characters(po,
> st->buf,
> +				sizeinunits, bpc, unit_bits,
> +				cval->lower_bound,
> cval->upper_bound, pc);
> +		} else {
> +			ret =3D per_put_many_bits(po, st->buf,
> +				sizeinunits * unit_bits);
> +		}
> +		if(ret) ASN__ENCODE_FAILED;
> +		ASN__ENCODED_OK(er);
> +	}
> +
> +	ASN_DEBUG("Encoding %d bytes", st->size);
> +
> +	if(sizeinunits =3D=3D 0) {
> +		if(uper_put_length(po, 0))
> +			ASN__ENCODE_FAILED;
> +		ASN__ENCODED_OK(er);
> +	}
> +
> +	buf =3D st->buf;
> +	while(sizeinunits) {
> +		ssize_t maySave =3D uper_put_length(po, sizeinunits);
> +		if(maySave < 0) ASN__ENCODE_FAILED;
> +
> +		ASN_DEBUG("Encoding %ld of %ld",
> +			(long)maySave, (long)sizeinunits);
> +
> +		if(bpc) {
> +			ret =3D OCTET_STRING_per_put_characters(po,
> buf,
> +				maySave, bpc, unit_bits,
> +				cval->lower_bound,
> cval->upper_bound, pc);
> +		} else {
> +			ret =3D per_put_many_bits(po, buf, maySave *
> unit_bits);
> +		}
> +		if(ret) ASN__ENCODE_FAILED;
> +
> +		if(bpc)
> +			buf +=3D maySave * bpc;
> +		else
> +			buf +=3D maySave >> 3;
> +		sizeinunits -=3D maySave;
> +		assert(!(maySave & 0x07) || !sizeinunits);
> +	}
> +
> +	ASN__ENCODED_OK(er);
> +}
> +
> +int
> +OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int
> ilevel,
> +	asn_app_consume_bytes_f *cb, void *app_key) {
> +	const char * const h2c =3D "0123456789ABCDEF";
> +	const OCTET_STRING_t *st =3D (const OCTET_STRING_t *)sptr;
> +	char scratch[16 * 3 + 4];
> +	char *p =3D scratch;
> +	uint8_t *buf;
> +	uint8_t *end;
> +	size_t i;
> +
> +	(void)td;	/* Unused argument */
> +
> +	if(!st || (!st->buf && st->size))
> +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
> +
> +	/*
> +	 * Dump the contents of the buffer in hexadecimal.
> +	 */
> +	buf =3D st->buf;
> +	end =3D buf + st->size;
> +	for(i =3D 0; buf < end; buf++, i++) {
> +		if(!(i % 16) && (i || st->size > 16)) {
> +			if(cb(scratch, p - scratch, app_key) < 0)
> +				return -1;
> +			_i_INDENT(1);
> +			p =3D scratch;
> +		}
> +		*p++ =3D h2c[(*buf >> 4) & 0x0F];
> +		*p++ =3D h2c[*buf & 0x0F];
> +		*p++ =3D 0x20;
> +	}
> +
> +	if(p > scratch) {
> +		p--;	/* Remove the tail space */
> +		if(cb(scratch, p - scratch, app_key) < 0)
> +			return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr,
> +		int ilevel, asn_app_consume_bytes_f *cb, void
> *app_key) {
> +	const OCTET_STRING_t *st =3D (const OCTET_STRING_t *)sptr;
> +
> +	(void)td;	/* Unused argument */
> +	(void)ilevel;	/* Unused argument */
> +
> +	if(st && (st->buf || !st->size)) {
> +		return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
> +	} else {
> +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
> +	}
> +}
> +
> +void
> +OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int
> contents_only) {
> +	OCTET_STRING_t *st =3D (OCTET_STRING_t *)sptr;
> +	asn_OCTET_STRING_specifics_t *specs;
> +	asn_struct_ctx_t *ctx;
> +	struct _stack *stck;
> +
> +	if(!td || !st)
> +		return;
> +
> +	specs =3D td->specifics
> +		    ? (asn_OCTET_STRING_specifics_t *)td->specifics
> +		    : &asn_DEF_OCTET_STRING_specs;
> +	ctx =3D (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
> +
> +	ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
> +
> +	if(st->buf) {
> +		FREEMEM(st->buf);
> +		st->buf =3D 0;
> +	}
> +
> +	/*
> +	 * Remove decode-time stack.
> +	 */
> +	stck =3D (struct _stack *)ctx->ptr;
> +	if(stck) {
> +		while(stck->tail) {
> +			struct _stack_el *sel =3D stck->tail;
> +			stck->tail =3D sel->prev;
> +			FREEMEM(sel);
> +		}
> +		FREEMEM(stck);
> +	}
> +
> +	if(!contents_only) {
> +		FREEMEM(st);
> +	}
> +}
> +
> +/*
> + * Conversion routines.
> + */
> +int
> +OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
> +	void *buf;
> +
> +	if(st =3D=3D 0 || (str =3D=3D 0 && len)) {
> +		errno =3D EINVAL;
> +		return -1;
> +	}
> +
> +	/*
> +	 * Clear the OCTET STRING.
> +	 */
> +	if(str =3D=3D NULL) {
> +		FREEMEM(st->buf);
> +		st->buf =3D 0;
> +		st->size =3D 0;
> +		return 0;
> +	}
> +
> +	/* Determine the original string size, if not explicitly
> given */
> +	if(len < 0)
> +		len =3D strlen(str);
> +
> +	/* Allocate and fill the memory */
> +	buf =3D MALLOC(len + 1);
> +	if(buf =3D=3D NULL)
> +		return -1;
> +
> +	memcpy(buf, str, len);
> +	((uint8_t *)buf)[len] =3D '\0';	/* Couldn't use
> memcpy(len+1)! */
> +	FREEMEM(st->buf);
> +	st->buf =3D (uint8_t *)buf;
> +	st->size =3D len;
> +
> +	return 0;
> +}
> +
> +OCTET_STRING_t *
> +OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str,
> int len) {
> +	asn_OCTET_STRING_specifics_t *specs =3D td->specifics
> +				? (asn_OCTET_STRING_specifics_t
> *)td->specifics
> +				: &asn_DEF_OCTET_STRING_specs;
> +	OCTET_STRING_t *st;
> +
> +	st =3D (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
> +	if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
> +		FREEMEM(st);
> +		st =3D NULL;
> +	}
> +
> +	return st;
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/OCTET_STRING.h
> b/libkmod/pkcs7/asn1c-gen/OCTET_STRING.h new file mode 100644
> index 000000000000..013c7b13f96c
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/OCTET_STRING.h
> @@ -0,0 +1,86 @@
> +/*-
> + * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	_OCTET_STRING_H_
> +#define	_OCTET_STRING_H_
> +
> +#include <asn_application.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef struct OCTET_STRING {
> +	uint8_t *buf;	/* Buffer with consecutive OCTET_STRING
> bits */
> +	int size;	/* Size of the buffer */
> +
> +	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer
> boundaries */ +} OCTET_STRING_t;
> +
> +extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING;
> +
> +asn_struct_free_f OCTET_STRING_free;
> +asn_struct_print_f OCTET_STRING_print;
> +asn_struct_print_f OCTET_STRING_print_utf8;
> +ber_type_decoder_f OCTET_STRING_decode_ber;
> +der_type_encoder_f OCTET_STRING_encode_der;
> +xer_type_decoder_f OCTET_STRING_decode_xer_hex;		/*
> Hexadecimal */ +xer_type_decoder_f
> OCTET_STRING_decode_xer_binary;	/* 01010111010 */
> +xer_type_decoder_f OCTET_STRING_decode_xer_utf8;	/*
> ASCII/UTF-8 */ +xer_type_encoder_f OCTET_STRING_encode_xer;
> +xer_type_encoder_f OCTET_STRING_encode_xer_utf8; +per_type_decoder_f
> OCTET_STRING_decode_uper; +per_type_encoder_f
> OCTET_STRING_encode_uper; +
> +/******************************
> + * Handy conversion routines. *
> + ******************************/
> +
> +/*
> + * This function clears the previous value of the OCTET STRING (if
> any)
> + * and then allocates a new memory with the specified content
> (str/size).
> + * If size =3D -1, the size of the original string will be determined
> + * using strlen(str).
> + * If str equals to NULL, the function will silently clear the
> + * current contents of the OCTET STRING.
> + * Returns 0 if it was possible to perform operation, -1 otherwise.
> + */
> +int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int
> size); +
> +/* Handy conversion from the C string into the OCTET STRING. */
> +#define	OCTET_STRING_fromString(s, str)
> OCTET_STRING_fromBuf(s, str, -1) +
> +/*
> + * Allocate and fill the new OCTET STRING and return a pointer to
> the newly
> + * allocated object. NULL is permitted in str: the function will
> just allocate
> + * empty OCTET STRING.
> + */
> +OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td,
> +	const char *str, int size);
> +
> +/****************************
> + * Internally useful stuff. *
> + ****************************/
> +
> +typedef const struct asn_OCTET_STRING_specifics_s {
> +	/*
> +	 * Target structure description.
> +	 */
> +	int struct_size;	/* Size of the structure */
> +	int ctx_offset;		/* Offset of the
> asn_struct_ctx_t member */ +
> +	enum asn_OS_Subvariant {
> +		ASN_OSUBV_ANY,	/* The open type (ANY) */
> +		ASN_OSUBV_BIT,	/* BIT STRING */
> +		ASN_OSUBV_STR,	/* String types, not
> {BMP,Universal}String  */
> +		ASN_OSUBV_U16,	/* 16-bit character
> (BMPString) */
> +		ASN_OSUBV_U32	/* 32-bit character
> (UniversalString) */
> +	} subvariant;
> +} asn_OCTET_STRING_specifics_t;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _OCTET_STRING_H_ */
> diff --git a/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c
> b/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c new file mode 100644
> index 000000000000..d4f6ffafc696
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.c
> @@ -0,0 +1,69 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "PKCS7ContentInfo.h"
> +
> +static asn_TYPE_member_t asn_MBR_PKCS7ContentInfo_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct PKCS7ContentInfo,
> contentType),
> +		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
> +		0,
> +		&asn_DEF_ContentType,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"contentType"
> +		},
> +	{ ATF_POINTER, 1, offsetof(struct PKCS7ContentInfo, content),
> +		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
> +		+1,	/* EXPLICIT tag at current level */
> +		&asn_DEF_SignedData,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"content"
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_PKCS7ContentInfo_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_PKCS7ContentInfo_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /*
> contentType */
> +    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, 0, 0 } /* content */
> +};
> +static asn_SEQUENCE_specifics_t asn_SPC_PKCS7ContentInfo_specs_1 =3D {
> +	sizeof(struct PKCS7ContentInfo),
> +	offsetof(struct PKCS7ContentInfo, _asn_ctx),
> +	asn_MAP_PKCS7ContentInfo_tag2el_1,
> +	2,	/* Count of tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_PKCS7ContentInfo =3D {
> +	"PKCS7ContentInfo",
> +	"PKCS7ContentInfo",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_PKCS7ContentInfo_tags_1,
> +	sizeof(asn_DEF_PKCS7ContentInfo_tags_1)
> +		/sizeof(asn_DEF_PKCS7ContentInfo_tags_1[0]), /* 1 */
> +	asn_DEF_PKCS7ContentInfo_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_PKCS7ContentInfo_tags_1)
> +		/sizeof(asn_DEF_PKCS7ContentInfo_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_PKCS7ContentInfo_1,
> +	2,	/* Elements count */
> +	&asn_SPC_PKCS7ContentInfo_specs_1	/* Additional specs
> */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h
> b/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h new file mode 100644
> index 000000000000..e9e84da96a75
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/PKCS7ContentInfo.h
> @@ -0,0 +1,45 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_PKCS7ContentInfo_H_
> +#define	_PKCS7ContentInfo_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include "ContentType.h"
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Forward declarations */
> +struct SignedData;
> +
> +/* PKCS7ContentInfo */
> +typedef struct PKCS7ContentInfo {
> +	ContentType_t	 contentType;
> +	struct SignedData	*content	/* OPTIONAL */;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} PKCS7ContentInfo_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_PKCS7ContentInfo;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +/* Referred external types */
> +#include "SignedData.h"
> +
> +#endif	/* _PKCS7ContentInfo_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c
> b/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c new file mode
> 100644 index 000000000000..d84ba39bb7b7
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.c
> @@ -0,0 +1,52 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "RelativeDistinguishedName.h"
> +
> +static asn_TYPE_member_t asn_MBR_RelativeDistinguishedName_1[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_AttributeValueAssertion,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t
> asn_DEF_RelativeDistinguishedName_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
> +};
> +static asn_SET_OF_specifics_t
> asn_SPC_RelativeDistinguishedName_specs_1 =3D {
> +	sizeof(struct RelativeDistinguishedName),
> +	offsetof(struct RelativeDistinguishedName, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +asn_TYPE_descriptor_t asn_DEF_RelativeDistinguishedName =3D {
> +	"RelativeDistinguishedName",
> +	"RelativeDistinguishedName",
> +	SET_OF_free,
> +	SET_OF_print,
> +	SET_OF_constraint,
> +	SET_OF_decode_ber,
> +	SET_OF_encode_der,
> +	SET_OF_decode_xer,
> +	SET_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_RelativeDistinguishedName_tags_1,
> +	sizeof(asn_DEF_RelativeDistinguishedName_tags_1)
> +		/sizeof(asn_DEF_RelativeDistinguishedName_tags_1[0]), /*
> 1 */
> +	asn_DEF_RelativeDistinguishedName_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_RelativeDistinguishedName_tags_1)
> +		/sizeof(asn_DEF_RelativeDistinguishedName_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_RelativeDistinguishedName_1,
> +	1,	/* Single element */
> +	&asn_SPC_RelativeDistinguishedName_specs_1	/*
> Additional specs */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h
> b/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h new file mode
> 100644 index 000000000000..48c906e258e9
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/RelativeDistinguishedName.h
> @@ -0,0 +1,44 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_RelativeDistinguishedName_H_
> +#define	_RelativeDistinguishedName_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <asn_SET_OF.h>
> +#include <constr_SET_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Forward declarations */
> +struct AttributeValueAssertion;
> +
> +/* RelativeDistinguishedName */
> +typedef struct RelativeDistinguishedName {
> +	A_SET_OF(struct AttributeValueAssertion) list;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} RelativeDistinguishedName_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_RelativeDistinguishedName;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +/* Referred external types */
> +#include "AttributeValueAssertion.h"
> +
> +#endif	/* _RelativeDistinguishedName_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c
> b/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c new file mode
> 100644 index 000000000000..4da761972db6
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.c
> @@ -0,0 +1,52 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "SetOfAuthenticatedAttribute.h"
> +
> +static asn_TYPE_member_t asn_MBR_SetOfAuthenticatedAttribute_1[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_AuthenticatedAttribute,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t
> asn_DEF_SetOfAuthenticatedAttribute_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
> +};
> +static asn_SET_OF_specifics_t
> asn_SPC_SetOfAuthenticatedAttribute_specs_1 =3D {
> +	sizeof(struct SetOfAuthenticatedAttribute),
> +	offsetof(struct SetOfAuthenticatedAttribute, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +asn_TYPE_descriptor_t asn_DEF_SetOfAuthenticatedAttribute =3D {
> +	"SetOfAuthenticatedAttribute",
> +	"SetOfAuthenticatedAttribute",
> +	SET_OF_free,
> +	SET_OF_print,
> +	SET_OF_constraint,
> +	SET_OF_decode_ber,
> +	SET_OF_encode_der,
> +	SET_OF_decode_xer,
> +	SET_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_SetOfAuthenticatedAttribute_tags_1,
> +	sizeof(asn_DEF_SetOfAuthenticatedAttribute_tags_1)
> +		/sizeof(asn_DEF_SetOfAuthenticatedAttribute_tags_1[0]), /*
> 1 */
> +	asn_DEF_SetOfAuthenticatedAttribute_tags_1,	/* Same
> as above */
> +	sizeof(asn_DEF_SetOfAuthenticatedAttribute_tags_1)
> +		/sizeof(asn_DEF_SetOfAuthenticatedAttribute_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_SetOfAuthenticatedAttribute_1,
> +	1,	/* Single element */
> +	&asn_SPC_SetOfAuthenticatedAttribute_specs_1	/*
> Additional specs */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h
> b/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h new file mode
> 100644 index 000000000000..65d1d57e8cc6
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SetOfAuthenticatedAttribute.h
> @@ -0,0 +1,44 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_SetOfAuthenticatedAttribute_H_
> +#define	_SetOfAuthenticatedAttribute_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <asn_SET_OF.h>
> +#include <constr_SET_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Forward declarations */
> +struct AuthenticatedAttribute;
> +
> +/* SetOfAuthenticatedAttribute */
> +typedef struct SetOfAuthenticatedAttribute {
> +	A_SET_OF(struct AuthenticatedAttribute) list;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} SetOfAuthenticatedAttribute_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_SetOfAuthenticatedAttribute;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +/* Referred external types */
> +#include "AuthenticatedAttribute.h"
> +
> +#endif	/* _SetOfAuthenticatedAttribute_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/SignedData.c
> b/libkmod/pkcs7/asn1c-gen/SignedData.c new file mode 100644
> index 000000000000..7db53fb3e6bb
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SignedData.c
> @@ -0,0 +1,227 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "SignedData.h"
> +
> +static asn_TYPE_member_t asn_MBR_certificates_5[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct certificates,
> choice.certSet),
> +		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
> +		-1,	/* IMPLICIT tag at current level */
> +		&asn_DEF_ExtendedCertificatesAndCertificates,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"certSet"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct certificates,
> choice.certSequence),
> +		(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
> +		-1,	/* IMPLICIT tag at current level */
> +		&asn_DEF_Certificates,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"certSequence"
> +		},
> +};
> +static const asn_TYPE_tag2member_t asn_MAP_certificates_tag2el_5[] =3D
> {
> +    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* certSet */
> +    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 } /* certSequence
> */ +};
> +static asn_CHOICE_specifics_t asn_SPC_certificates_specs_5 =3D {
> +	sizeof(struct certificates),
> +	offsetof(struct certificates, _asn_ctx),
> +	offsetof(struct certificates, present),
> +	sizeof(((struct certificates *)0)->present),
> +	asn_MAP_certificates_tag2el_5,
> +	2,	/* Count of tags in the map */
> +	0,
> +	-1	/* Extensions start */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_certificates_5 =3D {
> +	"certificates",
> +	"certificates",
> +	CHOICE_free,
> +	CHOICE_print,
> +	CHOICE_constraint,
> +	CHOICE_decode_ber,
> +	CHOICE_encode_der,
> +	CHOICE_decode_xer,
> +	CHOICE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	CHOICE_outmost_tag,
> +	0,	/* No effective tags (pointer) */
> +	0,	/* No effective tags (count) */
> +	0,	/* No tags (pointer) */
> +	0,	/* No tags (count) */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_certificates_5,
> +	2,	/* Elements count */
> +	&asn_SPC_certificates_specs_5	/* Additional specs */
> +};
> +
> +static asn_TYPE_member_t asn_MBR_crls_8[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct crls, choice.crlSet),
> +		(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
> +		-1,	/* IMPLICIT tag at current level */
> +		&asn_DEF_CertificateRevocationLists,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"crlSet"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct crls, choice.crlSequence),
> +		(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
> +		-1,	/* IMPLICIT tag at current level */
> +		&asn_DEF_CRLSequence,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"crlSequence"
> +		},
> +};
> +static const asn_TYPE_tag2member_t asn_MAP_crls_tag2el_8[] =3D {
> +    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* crlSet */
> +    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 1, 0, 0 } /* crlSequence */
> +};
> +static asn_CHOICE_specifics_t asn_SPC_crls_specs_8 =3D {
> +	sizeof(struct crls),
> +	offsetof(struct crls, _asn_ctx),
> +	offsetof(struct crls, present),
> +	sizeof(((struct crls *)0)->present),
> +	asn_MAP_crls_tag2el_8,
> +	2,	/* Count of tags in the map */
> +	0,
> +	-1	/* Extensions start */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_crls_8 =3D {
> +	"crls",
> +	"crls",
> +	CHOICE_free,
> +	CHOICE_print,
> +	CHOICE_constraint,
> +	CHOICE_decode_ber,
> +	CHOICE_encode_der,
> +	CHOICE_decode_xer,
> +	CHOICE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	CHOICE_outmost_tag,
> +	0,	/* No effective tags (pointer) */
> +	0,	/* No effective tags (count) */
> +	0,	/* No tags (pointer) */
> +	0,	/* No tags (count) */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_crls_8,
> +	2,	/* Elements count */
> +	&asn_SPC_crls_specs_8	/* Additional specs */
> +};
> +
> +static asn_TYPE_member_t asn_MBR_SignedData_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignedData, version),
> +		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
> +		0,
> +		&asn_DEF_INTEGER,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"version"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignedData,
> digestAlgorithms),
> +		-1 /* Ambiguous tag (CHOICE?) */,
> +		0,
> +		&asn_DEF_DigestAlgorithmIdentifiers,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"digestAlgorithms"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignedData, contentInfo),
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_ContentInfo,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"contentInfo"
> +		},
> +	{ ATF_POINTER, 2, offsetof(struct SignedData, certificates),
> +		-1 /* Ambiguous tag (CHOICE?) */,
> +		0,
> +		&asn_DEF_certificates_5,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"certificates"
> +		},
> +	{ ATF_POINTER, 1, offsetof(struct SignedData, crls),
> +		-1 /* Ambiguous tag (CHOICE?) */,
> +		0,
> +		&asn_DEF_crls_8,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"crls"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignedData, signerInfos),
> +		-1 /* Ambiguous tag (CHOICE?) */,
> +		0,
> +		&asn_DEF_SignerInfos,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"signerInfos"
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_SignedData_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static const asn_TYPE_tag2member_t asn_MAP_SignedData_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* version */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 2 }, /*
> daSequence */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 2, -1, 1 }, /*
> contentInfo */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 5, -2, 0 }, /*
> siSequence */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 1, 0, 1 }, /* daSet */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 5, -1, 0 }, /* siSet */
> +    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 3, 0, 0 }, /* certSet */
> +    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 4, 0, 0 }, /* crlSet */
> +    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 3, 0, 0 }, /* certSequence
> */
> +    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 4, 0, 0 } /* crlSequence */
> +};
> +static asn_SEQUENCE_specifics_t asn_SPC_SignedData_specs_1 =3D {
> +	sizeof(struct SignedData),
> +	offsetof(struct SignedData, _asn_ctx),
> +	asn_MAP_SignedData_tag2el_1,
> +	10,	/* Count of tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_SignedData =3D {
> +	"SignedData",
> +	"SignedData",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_SignedData_tags_1,
> +	sizeof(asn_DEF_SignedData_tags_1)
> +		/sizeof(asn_DEF_SignedData_tags_1[0]), /* 1 */
> +	asn_DEF_SignedData_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_SignedData_tags_1)
> +		/sizeof(asn_DEF_SignedData_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_SignedData_1,
> +	6,	/* Elements count */
> +	&asn_SPC_SignedData_specs_1	/* Additional specs */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/SignedData.h
> b/libkmod/pkcs7/asn1c-gen/SignedData.h new file mode 100644
> index 000000000000..7e92bca95e69
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SignedData.h
> @@ -0,0 +1,81 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_SignedData_H_
> +#define	_SignedData_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <INTEGER.h>
> +#include "DigestAlgorithmIdentifiers.h"
> +#include "ContentInfo.h"
> +#include "SignerInfos.h"
> +#include "ExtendedCertificatesAndCertificates.h"
> +#include "Certificates.h"
> +#include <constr_CHOICE.h>
> +#include "CertificateRevocationLists.h"
> +#include "CRLSequence.h"
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Dependencies */
> +typedef enum certificates_PR {
> +	certificates_PR_NOTHING,	/* No components present */
> +	certificates_PR_certSet,
> +	certificates_PR_certSequence
> +} certificates_PR;
> +typedef enum crls_PR {
> +	crls_PR_NOTHING,	/* No components present */
> +	crls_PR_crlSet,
> +	crls_PR_crlSequence
> +} crls_PR;
> +
> +/* SignedData */
> +typedef struct SignedData {
> +	INTEGER_t	 version;
> +	DigestAlgorithmIdentifiers_t	 digestAlgorithms;
> +	ContentInfo_t	 contentInfo;
> +	struct certificates {
> +		certificates_PR present;
> +		union SignedData__certificates_u {
> +
> ExtendedCertificatesAndCertificates_t	 certSet;
> +			Certificates_t	 certSequence;
> +		} choice;
> +	=09
> +		/* Context for parsing across buffer boundaries */
> +		asn_struct_ctx_t _asn_ctx;
> +	} *certificates;
> +	struct crls {
> +		crls_PR present;
> +		union SignedData__crls_u {
> +			CertificateRevocationLists_t	 crlSet;
> +			CRLSequence_t	 crlSequence;
> +		} choice;
> +	=09
> +		/* Context for parsing across buffer boundaries */
> +		asn_struct_ctx_t _asn_ctx;
> +	} *crls;
> +	SignerInfos_t	 signerInfos;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} SignedData_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_SignedData;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _SignedData_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/SignerIdentifier.c
> b/libkmod/pkcs7/asn1c-gen/SignerIdentifier.c new file mode 100644
> index 000000000000..bb5e3e25e4ed
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SignerIdentifier.c
> @@ -0,0 +1,65 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "SignerIdentifier.h"
> +
> +static asn_TYPE_member_t asn_MBR_SignerIdentifier_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignerIdentifier,
> choice.issuerAndSerialNumber),
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_IssuerAndSerialNumber,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"issuerAndSerialNumber"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignerIdentifier,
> choice.subjectKeyIdentifier),
> +		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
> +		-1,	/* IMPLICIT tag at current level */
> +		&asn_DEF_SubjectKeyIdentifier,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"subjectKeyIdentifier"
> +		},
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_SignerIdentifier_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 0, 0, 0 }, /*
> issuerAndSerialNumber */
> +    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, 0, 0 } /*
> subjectKeyIdentifier */ +};
> +static asn_CHOICE_specifics_t asn_SPC_SignerIdentifier_specs_1 =3D {
> +	sizeof(struct SignerIdentifier),
> +	offsetof(struct SignerIdentifier, _asn_ctx),
> +	offsetof(struct SignerIdentifier, present),
> +	sizeof(((struct SignerIdentifier *)0)->present),
> +	asn_MAP_SignerIdentifier_tag2el_1,
> +	2,	/* Count of tags in the map */
> +	0,
> +	-1	/* Extensions start */
> +};
> +asn_TYPE_descriptor_t asn_DEF_SignerIdentifier =3D {
> +	"SignerIdentifier",
> +	"SignerIdentifier",
> +	CHOICE_free,
> +	CHOICE_print,
> +	CHOICE_constraint,
> +	CHOICE_decode_ber,
> +	CHOICE_encode_der,
> +	CHOICE_decode_xer,
> +	CHOICE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	CHOICE_outmost_tag,
> +	0,	/* No effective tags (pointer) */
> +	0,	/* No effective tags (count) */
> +	0,	/* No tags (pointer) */
> +	0,	/* No tags (count) */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_SignerIdentifier_1,
> +	2,	/* Elements count */
> +	&asn_SPC_SignerIdentifier_specs_1	/* Additional specs
> */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/SignerIdentifier.h
> b/libkmod/pkcs7/asn1c-gen/SignerIdentifier.h new file mode 100644
> index 000000000000..7eb253e5673d
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SignerIdentifier.h
> @@ -0,0 +1,50 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_SignerIdentifier_H_
> +#define	_SignerIdentifier_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include "IssuerAndSerialNumber.h"
> +#include "SubjectKeyIdentifier.h"
> +#include <constr_CHOICE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Dependencies */
> +typedef enum SignerIdentifier_PR {
> +	SignerIdentifier_PR_NOTHING,	/* No components present
> */
> +	SignerIdentifier_PR_issuerAndSerialNumber,
> +	SignerIdentifier_PR_subjectKeyIdentifier
> +} SignerIdentifier_PR;
> +
> +/* SignerIdentifier */
> +typedef struct SignerIdentifier {
> +	SignerIdentifier_PR present;
> +	union SignerIdentifier_u {
> +		IssuerAndSerialNumber_t
> issuerAndSerialNumber;
> +		SubjectKeyIdentifier_t	 subjectKeyIdentifier;
> +	} choice;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} SignerIdentifier_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_SignerIdentifier;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _SignerIdentifier_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/SignerInfo.c
> b/libkmod/pkcs7/asn1c-gen/SignerInfo.c new file mode 100644
> index 000000000000..8e32418c2f63
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SignerInfo.c
> @@ -0,0 +1,371 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "SignerInfo.h"
> +
> +static asn_TYPE_member_t asn_MBR_aaSequence_7[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_AuthenticatedAttribute,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_aaSequence_tags_7[] =3D {
> +	(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_aaSequence_specs_7 =3D {
> +	sizeof(struct aaSequence),
> +	offsetof(struct aaSequence, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_aaSequence_7 =3D {
> +	"aaSequence",
> +	"aaSequence",
> +	SEQUENCE_OF_free,
> +	SEQUENCE_OF_print,
> +	SEQUENCE_OF_constraint,
> +	SEQUENCE_OF_decode_ber,
> +	SEQUENCE_OF_encode_der,
> +	SEQUENCE_OF_decode_xer,
> +	SEQUENCE_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_aaSequence_tags_7,
> +	sizeof(asn_DEF_aaSequence_tags_7)
> +		/sizeof(asn_DEF_aaSequence_tags_7[0]), /* 2 */
> +	asn_DEF_aaSequence_tags_7,	/* Same as above */
> +	sizeof(asn_DEF_aaSequence_tags_7)
> +		/sizeof(asn_DEF_aaSequence_tags_7[0]), /* 2 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_aaSequence_7,
> +	1,	/* Single element */
> +	&asn_SPC_aaSequence_specs_7	/* Additional specs */
> +};
> +
> +static asn_TYPE_member_t asn_MBR_authenticatedAttributes_5[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct authenticatedAttributes,
> choice.aaSet),
> +		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
> +		-1,	/* IMPLICIT tag at current level */
> +		&asn_DEF_SetOfAuthenticatedAttribute,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"aaSet"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct authenticatedAttributes,
> choice.aaSequence),
> +		(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
> +		0,
> +		&asn_DEF_aaSequence_7,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"aaSequence"
> +		},
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_authenticatedAttributes_tag2el_5[] =3D {
> +    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* aaSet */
> +    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 } /* aaSequence */
> +};
> +static asn_CHOICE_specifics_t
> asn_SPC_authenticatedAttributes_specs_5 =3D {
> +	sizeof(struct authenticatedAttributes),
> +	offsetof(struct authenticatedAttributes, _asn_ctx),
> +	offsetof(struct authenticatedAttributes, present),
> +	sizeof(((struct authenticatedAttributes *)0)->present),
> +	asn_MAP_authenticatedAttributes_tag2el_5,
> +	2,	/* Count of tags in the map */
> +	0,
> +	-1	/* Extensions start */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_authenticatedAttributes_5 =3D {
> +	"authenticatedAttributes",
> +	"authenticatedAttributes",
> +	CHOICE_free,
> +	CHOICE_print,
> +	CHOICE_constraint,
> +	CHOICE_decode_ber,
> +	CHOICE_encode_der,
> +	CHOICE_decode_xer,
> +	CHOICE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	CHOICE_outmost_tag,
> +	0,	/* No effective tags (pointer) */
> +	0,	/* No effective tags (count) */
> +	0,	/* No tags (pointer) */
> +	0,	/* No tags (count) */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_authenticatedAttributes_5,
> +	2,	/* Elements count */
> +	&asn_SPC_authenticatedAttributes_specs_5	/*
> Additional specs */ +};
> +
> +static asn_TYPE_member_t asn_MBR_uaSet_12[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_UnauthenticatedAttribute,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_uaSet_tags_12[] =3D {
> +	(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
> +	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_uaSet_specs_12 =3D {
> +	sizeof(struct uaSet),
> +	offsetof(struct uaSet, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_uaSet_12 =3D {
> +	"uaSet",
> +	"uaSet",
> +	SET_OF_free,
> +	SET_OF_print,
> +	SET_OF_constraint,
> +	SET_OF_decode_ber,
> +	SET_OF_encode_der,
> +	SET_OF_decode_xer,
> +	SET_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_uaSet_tags_12,
> +	sizeof(asn_DEF_uaSet_tags_12)
> +		/sizeof(asn_DEF_uaSet_tags_12[0]) - 1, /* 1 */
> +	asn_DEF_uaSet_tags_12,	/* Same as above */
> +	sizeof(asn_DEF_uaSet_tags_12)
> +		/sizeof(asn_DEF_uaSet_tags_12[0]), /* 2 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_uaSet_12,
> +	1,	/* Single element */
> +	&asn_SPC_uaSet_specs_12	/* Additional specs */
> +};
> +
> +static asn_TYPE_member_t asn_MBR_uaSequence_14[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_UnauthenticatedAttribute,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_uaSequence_tags_14[] =3D {
> +	(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_uaSequence_specs_14 =3D {
> +	sizeof(struct uaSequence),
> +	offsetof(struct uaSequence, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_uaSequence_14 =3D {
> +	"uaSequence",
> +	"uaSequence",
> +	SEQUENCE_OF_free,
> +	SEQUENCE_OF_print,
> +	SEQUENCE_OF_constraint,
> +	SEQUENCE_OF_decode_ber,
> +	SEQUENCE_OF_encode_der,
> +	SEQUENCE_OF_decode_xer,
> +	SEQUENCE_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_uaSequence_tags_14,
> +	sizeof(asn_DEF_uaSequence_tags_14)
> +		/sizeof(asn_DEF_uaSequence_tags_14[0]) - 1, /* 1 */
> +	asn_DEF_uaSequence_tags_14,	/* Same as above */
> +	sizeof(asn_DEF_uaSequence_tags_14)
> +		/sizeof(asn_DEF_uaSequence_tags_14[0]), /* 2 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_uaSequence_14,
> +	1,	/* Single element */
> +	&asn_SPC_uaSequence_specs_14	/* Additional specs */
> +};
> +
> +static asn_TYPE_member_t asn_MBR_unauthenticatedAttributes_11[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct unauthenticatedAttributes,
> choice.uaSet),
> +		(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
> +		0,
> +		&asn_DEF_uaSet_12,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"uaSet"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct unauthenticatedAttributes,
> choice.uaSequence),
> +		(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
> +		0,
> +		&asn_DEF_uaSequence_14,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"uaSequence"
> +		},
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_unauthenticatedAttributes_tag2el_11[] =3D {
> +    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* uaSet */
> +    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 1, 0, 0 } /* uaSequence */
> +};
> +static asn_CHOICE_specifics_t
> asn_SPC_unauthenticatedAttributes_specs_11 =3D {
> +	sizeof(struct unauthenticatedAttributes),
> +	offsetof(struct unauthenticatedAttributes, _asn_ctx),
> +	offsetof(struct unauthenticatedAttributes, present),
> +	sizeof(((struct unauthenticatedAttributes *)0)->present),
> +	asn_MAP_unauthenticatedAttributes_tag2el_11,
> +	2,	/* Count of tags in the map */
> +	0,
> +	-1	/* Extensions start */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_unauthenticatedAttributes_11 =3D {
> +	"unauthenticatedAttributes",
> +	"unauthenticatedAttributes",
> +	CHOICE_free,
> +	CHOICE_print,
> +	CHOICE_constraint,
> +	CHOICE_decode_ber,
> +	CHOICE_encode_der,
> +	CHOICE_decode_xer,
> +	CHOICE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	CHOICE_outmost_tag,
> +	0,	/* No effective tags (pointer) */
> +	0,	/* No effective tags (count) */
> +	0,	/* No tags (pointer) */
> +	0,	/* No tags (count) */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_unauthenticatedAttributes_11,
> +	2,	/* Elements count */
> +	&asn_SPC_unauthenticatedAttributes_specs_11	/*
> Additional specs */ +};
> +
> +static asn_TYPE_member_t asn_MBR_SignerInfo_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo, version),
> +		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
> +		0,
> +		&asn_DEF_INTEGER,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"version"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo, sid),
> +		-1 /* Ambiguous tag (CHOICE?) */,
> +		0,
> +		&asn_DEF_SignerIdentifier,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"sid"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo,
> digestAlgorithm),
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_DigestAlgorithmIdentifier,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"digestAlgorithm"
> +		},
> +	{ ATF_POINTER, 1, offsetof(struct SignerInfo,
> authenticatedAttributes),
> +		-1 /* Ambiguous tag (CHOICE?) */,
> +		0,
> +		&asn_DEF_authenticatedAttributes_5,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"authenticatedAttributes"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo,
> digestEncryptionAlgorithm),
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_DigestEncryptionAlgorithmIdentifier,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"digestEncryptionAlgorithm"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfo,
> encryptedDigest),
> +		(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)),
> +		0,
> +		&asn_DEF_EncryptedDigest,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"encryptedDigest"
> +		},
> +	{ ATF_POINTER, 1, offsetof(struct SignerInfo,
> unauthenticatedAttributes),
> +		-1 /* Ambiguous tag (CHOICE?) */,
> +		0,
> +		&asn_DEF_unauthenticatedAttributes_11,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"unauthenticatedAttributes"
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_SignerInfo_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static const asn_TYPE_tag2member_t asn_MAP_SignerInfo_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* version */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 5, 0, 0 }, /*
> encryptedDigest */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 2 }, /*
> issuerAndSerialNumber */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 2, -1, 1 }, /*
> digestAlgorithm */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 4, -2, 0 }, /*
> digestEncryptionAlgorithm */
> +    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, 0, 1 }, /*
> subjectKeyIdentifier */
> +    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 3, -1, 0 }, /* aaSet */
> +    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 6, 0, 0 }, /* uaSet */
> +    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 3, 0, 0 }, /* aaSequence */
> +    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 6, 0, 0 } /* uaSequence */
> +};
> +static asn_SEQUENCE_specifics_t asn_SPC_SignerInfo_specs_1 =3D {
> +	sizeof(struct SignerInfo),
> +	offsetof(struct SignerInfo, _asn_ctx),
> +	asn_MAP_SignerInfo_tag2el_1,
> +	10,	/* Count of tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_SignerInfo =3D {
> +	"SignerInfo",
> +	"SignerInfo",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_SignerInfo_tags_1,
> +	sizeof(asn_DEF_SignerInfo_tags_1)
> +		/sizeof(asn_DEF_SignerInfo_tags_1[0]), /* 1 */
> +	asn_DEF_SignerInfo_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_SignerInfo_tags_1)
> +		/sizeof(asn_DEF_SignerInfo_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_SignerInfo_1,
> +	7,	/* Elements count */
> +	&asn_SPC_SignerInfo_specs_1	/* Additional specs */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/SignerInfo.h
> b/libkmod/pkcs7/asn1c-gen/SignerInfo.h new file mode 100644
> index 000000000000..1cc8c986ff4e
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SignerInfo.h
> @@ -0,0 +1,107 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_SignerInfo_H_
> +#define	_SignerInfo_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <INTEGER.h>
> +#include "SignerIdentifier.h"
> +#include "DigestAlgorithmIdentifier.h"
> +#include "DigestEncryptionAlgorithmIdentifier.h"
> +#include "EncryptedDigest.h"
> +#include "SetOfAuthenticatedAttribute.h"
> +#include <asn_SEQUENCE_OF.h>
> +#include <constr_SEQUENCE_OF.h>
> +#include <constr_CHOICE.h>
> +#include <asn_SET_OF.h>
> +#include <constr_SET_OF.h>
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Dependencies */
> +typedef enum authenticatedAttributes_PR {
> +	authenticatedAttributes_PR_NOTHING,	/* No components
> present */
> +	authenticatedAttributes_PR_aaSet,
> +	authenticatedAttributes_PR_aaSequence
> +} authenticatedAttributes_PR;
> +typedef enum unauthenticatedAttributes_PR {
> +	unauthenticatedAttributes_PR_NOTHING,	/* No
> components present */
> +	unauthenticatedAttributes_PR_uaSet,
> +	unauthenticatedAttributes_PR_uaSequence
> +} unauthenticatedAttributes_PR;
> +
> +/* Forward declarations */
> +struct AuthenticatedAttribute;
> +struct UnauthenticatedAttribute;
> +
> +/* SignerInfo */
> +typedef struct SignerInfo {
> +	INTEGER_t	 version;
> +	SignerIdentifier_t	 sid;
> +	DigestAlgorithmIdentifier_t	 digestAlgorithm;
> +	struct authenticatedAttributes {
> +		authenticatedAttributes_PR present;
> +		union SignerInfo__authenticatedAttributes_u {
> +			SetOfAuthenticatedAttribute_t	 aaSet;
> +			struct aaSequence {
> +				A_SEQUENCE_OF(struct
> AuthenticatedAttribute) list;
> +			=09
> +				/* Context for parsing across buffer
> boundaries */
> +				asn_struct_ctx_t _asn_ctx;
> +			} aaSequence;
> +		} choice;
> +	=09
> +		/* Context for parsing across buffer boundaries */
> +		asn_struct_ctx_t _asn_ctx;
> +	} *authenticatedAttributes;
> +	DigestEncryptionAlgorithmIdentifier_t
> digestEncryptionAlgorithm;
> +	EncryptedDigest_t	 encryptedDigest;
> +	struct unauthenticatedAttributes {
> +		unauthenticatedAttributes_PR present;
> +		union SignerInfo__unauthenticatedAttributes_u {
> +			struct uaSet {
> +				A_SET_OF(struct
> UnauthenticatedAttribute) list;
> +			=09
> +				/* Context for parsing across buffer
> boundaries */
> +				asn_struct_ctx_t _asn_ctx;
> +			} uaSet;
> +			struct uaSequence {
> +				A_SEQUENCE_OF(struct
> UnauthenticatedAttribute) list;
> +			=09
> +				/* Context for parsing across buffer
> boundaries */
> +				asn_struct_ctx_t _asn_ctx;
> +			} uaSequence;
> +		} choice;
> +	=09
> +		/* Context for parsing across buffer boundaries */
> +		asn_struct_ctx_t _asn_ctx;
> +	} *unauthenticatedAttributes;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} SignerInfo_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_SignerInfo;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +/* Referred external types */
> +#include "AuthenticatedAttribute.h"
> +#include "UnauthenticatedAttribute.h"
> +
> +#endif	/* _SignerInfo_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/SignerInfos.c
> b/libkmod/pkcs7/asn1c-gen/SignerInfos.c new file mode 100644
> index 000000000000..36e3ca444339
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SignerInfos.c
> @@ -0,0 +1,153 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "SignerInfos.h"
> +
> +static asn_TYPE_member_t asn_MBR_siSet_2[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_SignerInfo,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_siSet_tags_2[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_siSet_specs_2 =3D {
> +	sizeof(struct siSet),
> +	offsetof(struct siSet, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_siSet_2 =3D {
> +	"siSet",
> +	"siSet",
> +	SET_OF_free,
> +	SET_OF_print,
> +	SET_OF_constraint,
> +	SET_OF_decode_ber,
> +	SET_OF_encode_der,
> +	SET_OF_decode_xer,
> +	SET_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_siSet_tags_2,
> +	sizeof(asn_DEF_siSet_tags_2)
> +		/sizeof(asn_DEF_siSet_tags_2[0]), /* 1 */
> +	asn_DEF_siSet_tags_2,	/* Same as above */
> +	sizeof(asn_DEF_siSet_tags_2)
> +		/sizeof(asn_DEF_siSet_tags_2[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_siSet_2,
> +	1,	/* Single element */
> +	&asn_SPC_siSet_specs_2	/* Additional specs */
> +};
> +
> +static asn_TYPE_member_t asn_MBR_siSequence_4[] =3D {
> +	{ ATF_POINTER, 0, 0,
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_SignerInfo,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_siSequence_tags_4[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_siSequence_specs_4 =3D {
> +	sizeof(struct siSequence),
> +	offsetof(struct siSequence, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +static /* Use -fall-defs-global to expose */
> +asn_TYPE_descriptor_t asn_DEF_siSequence_4 =3D {
> +	"siSequence",
> +	"siSequence",
> +	SEQUENCE_OF_free,
> +	SEQUENCE_OF_print,
> +	SEQUENCE_OF_constraint,
> +	SEQUENCE_OF_decode_ber,
> +	SEQUENCE_OF_encode_der,
> +	SEQUENCE_OF_decode_xer,
> +	SEQUENCE_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_siSequence_tags_4,
> +	sizeof(asn_DEF_siSequence_tags_4)
> +		/sizeof(asn_DEF_siSequence_tags_4[0]), /* 1 */
> +	asn_DEF_siSequence_tags_4,	/* Same as above */
> +	sizeof(asn_DEF_siSequence_tags_4)
> +		/sizeof(asn_DEF_siSequence_tags_4[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_siSequence_4,
> +	1,	/* Single element */
> +	&asn_SPC_siSequence_specs_4	/* Additional specs */
> +};
> +
> +static asn_TYPE_member_t asn_MBR_SignerInfos_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfos, choice.siSet),
> +		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
> +		0,
> +		&asn_DEF_siSet_2,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"siSet"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct SignerInfos,
> choice.siSequence),
> +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
> +		0,
> +		&asn_DEF_siSequence_4,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"siSequence"
> +		},
> +};
> +static const asn_TYPE_tag2member_t asn_MAP_SignerInfos_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 0 }, /*
> siSequence */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 0, 0, 0 } /* siSet */
> +};
> +static asn_CHOICE_specifics_t asn_SPC_SignerInfos_specs_1 =3D {
> +	sizeof(struct SignerInfos),
> +	offsetof(struct SignerInfos, _asn_ctx),
> +	offsetof(struct SignerInfos, present),
> +	sizeof(((struct SignerInfos *)0)->present),
> +	asn_MAP_SignerInfos_tag2el_1,
> +	2,	/* Count of tags in the map */
> +	0,
> +	-1	/* Extensions start */
> +};
> +asn_TYPE_descriptor_t asn_DEF_SignerInfos =3D {
> +	"SignerInfos",
> +	"SignerInfos",
> +	CHOICE_free,
> +	CHOICE_print,
> +	CHOICE_constraint,
> +	CHOICE_decode_ber,
> +	CHOICE_encode_der,
> +	CHOICE_decode_xer,
> +	CHOICE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	CHOICE_outmost_tag,
> +	0,	/* No effective tags (pointer) */
> +	0,	/* No effective tags (count) */
> +	0,	/* No tags (pointer) */
> +	0,	/* No tags (count) */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_SignerInfos_1,
> +	2,	/* Elements count */
> +	&asn_SPC_SignerInfos_specs_1	/* Additional specs */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/SignerInfos.h
> b/libkmod/pkcs7/asn1c-gen/SignerInfos.h new file mode 100644
> index 000000000000..cc7014623883
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SignerInfos.h
> @@ -0,0 +1,68 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_SignerInfos_H_
> +#define	_SignerInfos_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <asn_SET_OF.h>
> +#include <constr_SET_OF.h>
> +#include <asn_SEQUENCE_OF.h>
> +#include <constr_SEQUENCE_OF.h>
> +#include <constr_CHOICE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Dependencies */
> +typedef enum SignerInfos_PR {
> +	SignerInfos_PR_NOTHING,	/* No components present */
> +	SignerInfos_PR_siSet,
> +	SignerInfos_PR_siSequence
> +} SignerInfos_PR;
> +
> +/* Forward declarations */
> +struct SignerInfo;
> +
> +/* SignerInfos */
> +typedef struct SignerInfos {
> +	SignerInfos_PR present;
> +	union SignerInfos_u {
> +		struct siSet {
> +			A_SET_OF(struct SignerInfo) list;
> +		=09
> +			/* Context for parsing across buffer
> boundaries */
> +			asn_struct_ctx_t _asn_ctx;
> +		} siSet;
> +		struct siSequence {
> +			A_SEQUENCE_OF(struct SignerInfo) list;
> +		=09
> +			/* Context for parsing across buffer
> boundaries */
> +			asn_struct_ctx_t _asn_ctx;
> +		} siSequence;
> +	} choice;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} SignerInfos_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_SignerInfos;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +/* Referred external types */
> +#include "SignerInfo.h"
> +
> +#endif	/* _SignerInfos_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c
> b/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c new file mode 100644
> index 000000000000..2bde5c462489
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.c
> @@ -0,0 +1,109 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "SubjectKeyIdentifier.h"
> +
> +int
> +SubjectKeyIdentifier_constraint(asn_TYPE_descriptor_t *td, const
> void *sptr,
> +			asn_app_constraint_failed_f *ctfailcb, void
> *app_key) {
> +	/* Replace with underlying type checker */
> +	td->check_constraints =3D
> asn_DEF_OCTET_STRING.check_constraints;
> +	return td->check_constraints(td, sptr, ctfailcb, app_key);
> +}
> +
> +/*
> + * This type is implemented using OCTET_STRING,
> + * so here we adjust the DEF accordingly.
> + */
> +static void
> +SubjectKeyIdentifier_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t
> *td) {
> +	td->free_struct    =3D asn_DEF_OCTET_STRING.free_struct;
> +	td->print_struct   =3D asn_DEF_OCTET_STRING.print_struct;
> +	td->check_constraints =3D
> asn_DEF_OCTET_STRING.check_constraints;
> +	td->ber_decoder    =3D asn_DEF_OCTET_STRING.ber_decoder;
> +	td->der_encoder    =3D asn_DEF_OCTET_STRING.der_encoder;
> +	td->xer_decoder    =3D asn_DEF_OCTET_STRING.xer_decoder;
> +	td->xer_encoder    =3D asn_DEF_OCTET_STRING.xer_encoder;
> +	td->uper_decoder   =3D asn_DEF_OCTET_STRING.uper_decoder;
> +	td->uper_encoder   =3D asn_DEF_OCTET_STRING.uper_encoder;
> +	if(!td->per_constraints)
> +		td->per_constraints =3D
> asn_DEF_OCTET_STRING.per_constraints;
> +	td->elements       =3D asn_DEF_OCTET_STRING.elements;
> +	td->elements_count =3D asn_DEF_OCTET_STRING.elements_count;
> +	td->specifics      =3D asn_DEF_OCTET_STRING.specifics;
> +}
> +
> +void
> +SubjectKeyIdentifier_free(asn_TYPE_descriptor_t *td,
> +		void *struct_ptr, int contents_only) {
> +	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
> +	td->free_struct(td, struct_ptr, contents_only);
> +}
> +
> +int
> +SubjectKeyIdentifier_print(asn_TYPE_descriptor_t *td, const void
> *struct_ptr,
> +		int ilevel, asn_app_consume_bytes_f *cb, void
> *app_key) {
> +	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
> +	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
> +}
> +
> +asn_dec_rval_t
> +SubjectKeyIdentifier_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const void *bufptr, size_t size,
> int tag_mode) {
> +	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
> +	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr,
> size, tag_mode); +}
> +
> +asn_enc_rval_t
> +SubjectKeyIdentifier_encode_der(asn_TYPE_descriptor_t *td,
> +		void *structure, int tag_mode, ber_tlv_tag_t tag,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
> +	return td->der_encoder(td, structure, tag_mode, tag, cb,
> app_key); +}
> +
> +asn_dec_rval_t
> +SubjectKeyIdentifier_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
> asn_TYPE_descriptor_t *td,
> +		void **structure, const char *opt_mname, const void
> *bufptr, size_t size) {
> +	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
> +	return td->xer_decoder(opt_codec_ctx, td, structure,
> opt_mname, bufptr, size); +}
> +
> +asn_enc_rval_t
> +SubjectKeyIdentifier_encode_xer(asn_TYPE_descriptor_t *td, void
> *structure,
> +		int ilevel, enum xer_encoder_flags_e flags,
> +		asn_app_consume_bytes_f *cb, void *app_key) {
> +	SubjectKeyIdentifier_1_inherit_TYPE_descriptor(td);
> +	return td->xer_encoder(td, structure, ilevel, flags, cb,
> app_key); +}
> +
> +static const ber_tlv_tag_t asn_DEF_SubjectKeyIdentifier_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
> +};
> +asn_TYPE_descriptor_t asn_DEF_SubjectKeyIdentifier =3D {
> +	"SubjectKeyIdentifier",
> +	"SubjectKeyIdentifier",
> +	SubjectKeyIdentifier_free,
> +	SubjectKeyIdentifier_print,
> +	SubjectKeyIdentifier_constraint,
> +	SubjectKeyIdentifier_decode_ber,
> +	SubjectKeyIdentifier_encode_der,
> +	SubjectKeyIdentifier_decode_xer,
> +	SubjectKeyIdentifier_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_SubjectKeyIdentifier_tags_1,
> +	sizeof(asn_DEF_SubjectKeyIdentifier_tags_1)
> +		/sizeof(asn_DEF_SubjectKeyIdentifier_tags_1[0]), /*
> 1 */
> +	asn_DEF_SubjectKeyIdentifier_tags_1,	/* Same as above
> */
> +	sizeof(asn_DEF_SubjectKeyIdentifier_tags_1)
> +		/sizeof(asn_DEF_SubjectKeyIdentifier_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	0, 0,	/* No members */
> +	0	/* No specifics */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h
> b/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h new file mode 100644
> index 000000000000..fb1d276adf3a
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/SubjectKeyIdentifier.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_SubjectKeyIdentifier_H_
> +#define	_SubjectKeyIdentifier_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <OCTET_STRING.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* SubjectKeyIdentifier */
> +typedef OCTET_STRING_t	 SubjectKeyIdentifier_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_SubjectKeyIdentifier;
> +asn_struct_free_f SubjectKeyIdentifier_free;
> +asn_struct_print_f SubjectKeyIdentifier_print;
> +asn_constr_check_f SubjectKeyIdentifier_constraint;
> +ber_type_decoder_f SubjectKeyIdentifier_decode_ber;
> +der_type_encoder_f SubjectKeyIdentifier_encode_der;
> +xer_type_decoder_f SubjectKeyIdentifier_decode_xer;
> +xer_type_encoder_f SubjectKeyIdentifier_encode_xer;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _SubjectKeyIdentifier_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c
> b/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c new file mode
> 100644 index 000000000000..3a6b6548c85f
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.c
> @@ -0,0 +1,69 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "UnauthenticatedAttribute.h"
> +
> +static asn_TYPE_member_t asn_MBR_UnauthenticatedAttribute_1[] =3D {
> +	{ ATF_NOFLAGS, 0, offsetof(struct UnauthenticatedAttribute,
> type),
> +		(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
> +		0,
> +		&asn_DEF_OBJECT_IDENTIFIER,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"type"
> +		},
> +	{ ATF_NOFLAGS, 0, offsetof(struct UnauthenticatedAttribute,
> values),
> +		(ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
> +		0,
> +		&asn_DEF_Values,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		"values"
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_UnauthenticatedAttribute_tags_1[]
> =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
> +};
> +static const asn_TYPE_tag2member_t
> asn_MAP_UnauthenticatedAttribute_tag2el_1[] =3D {
> +    { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /* type */
> +    { (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)), 1, 0, 0 } /* values */
> +};
> +static asn_SEQUENCE_specifics_t
> asn_SPC_UnauthenticatedAttribute_specs_1 =3D {
> +	sizeof(struct UnauthenticatedAttribute),
> +	offsetof(struct UnauthenticatedAttribute, _asn_ctx),
> +	asn_MAP_UnauthenticatedAttribute_tag2el_1,
> +	2,	/* Count of tags in the map */
> +	0, 0, 0,	/* Optional elements (not needed) */
> +	-1,	/* Start extensions */
> +	-1	/* Stop extensions */
> +};
> +asn_TYPE_descriptor_t asn_DEF_UnauthenticatedAttribute =3D {
> +	"UnauthenticatedAttribute",
> +	"UnauthenticatedAttribute",
> +	SEQUENCE_free,
> +	SEQUENCE_print,
> +	SEQUENCE_constraint,
> +	SEQUENCE_decode_ber,
> +	SEQUENCE_encode_der,
> +	SEQUENCE_decode_xer,
> +	SEQUENCE_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_UnauthenticatedAttribute_tags_1,
> +	sizeof(asn_DEF_UnauthenticatedAttribute_tags_1)
> +		/sizeof(asn_DEF_UnauthenticatedAttribute_tags_1[0]), /*
> 1 */
> +	asn_DEF_UnauthenticatedAttribute_tags_1,	/* Same as
> above */
> +	sizeof(asn_DEF_UnauthenticatedAttribute_tags_1)
> +		/sizeof(asn_DEF_UnauthenticatedAttribute_tags_1[0]), /*
> 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_UnauthenticatedAttribute_1,
> +	2,	/* Elements count */
> +	&asn_SPC_UnauthenticatedAttribute_specs_1	/*
> Additional specs */ +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h
> b/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h new file mode
> 100644 index 000000000000..5837608b97ce
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/UnauthenticatedAttribute.h
> @@ -0,0 +1,40 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_UnauthenticatedAttribute_H_
> +#define	_UnauthenticatedAttribute_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <OBJECT_IDENTIFIER.h>
> +#include "Values.h"
> +#include <constr_SEQUENCE.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* UnauthenticatedAttribute */
> +typedef struct UnauthenticatedAttribute {
> +	OBJECT_IDENTIFIER_t	 type;
> +	Values_t	 values;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} UnauthenticatedAttribute_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_UnauthenticatedAttribute;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _UnauthenticatedAttribute_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/Values.c
> b/libkmod/pkcs7/asn1c-gen/Values.c new file mode 100644
> index 000000000000..def8389e63d2
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Values.c
> @@ -0,0 +1,52 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#include "Values.h"
> +
> +static asn_TYPE_member_t asn_MBR_Values_1[] =3D {
> +	{ ATF_OPEN_TYPE | ATF_POINTER, 0, 0,
> +		-1 /* Ambiguous tag (ANY?) */,
> +		0,
> +		&asn_DEF_ANY,
> +		0,	/* Defer constraints checking to the
> member type */
> +		0,	/* PER is not compiled, use -gen-PER */
> +		0,
> +		""
> +		},
> +};
> +static const ber_tlv_tag_t asn_DEF_Values_tags_1[] =3D {
> +	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
> +};
> +static asn_SET_OF_specifics_t asn_SPC_Values_specs_1 =3D {
> +	sizeof(struct Values),
> +	offsetof(struct Values, _asn_ctx),
> +	0,	/* XER encoding is XMLDelimitedItemList */
> +};
> +asn_TYPE_descriptor_t asn_DEF_Values =3D {
> +	"Values",
> +	"Values",
> +	SET_OF_free,
> +	SET_OF_print,
> +	SET_OF_constraint,
> +	SET_OF_decode_ber,
> +	SET_OF_encode_der,
> +	SET_OF_decode_xer,
> +	SET_OF_encode_xer,
> +	0, 0,	/* No PER support, use "-gen-PER" to enable */
> +	0,	/* Use generic outmost tag fetcher */
> +	asn_DEF_Values_tags_1,
> +	sizeof(asn_DEF_Values_tags_1)
> +		/sizeof(asn_DEF_Values_tags_1[0]), /* 1 */
> +	asn_DEF_Values_tags_1,	/* Same as above */
> +	sizeof(asn_DEF_Values_tags_1)
> +		/sizeof(asn_DEF_Values_tags_1[0]), /* 1 */
> +	0,	/* No PER visible constraints */
> +	asn_MBR_Values_1,
> +	1,	/* Single element */
> +	&asn_SPC_Values_specs_1	/* Additional specs */
> +};
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/Values.h
> b/libkmod/pkcs7/asn1c-gen/Values.h new file mode 100644
> index 000000000000..8328a1163cac
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/Values.h
> @@ -0,0 +1,39 @@
> +/*
> + * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
> + * From ASN.1 module "PKCS7"
> + * 	found in "../pkcs7.asn1"
> + * 	`asn1c -fwide-types`
> + */
> +
> +#ifndef	_Values_H_
> +#define	_Values_H_
> +
> +
> +#include <asn_application.h>
> +
> +/* Including external dependencies */
> +#include <ANY.h>
> +#include <asn_SET_OF.h>
> +#include <constr_SET_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Values */
> +typedef struct Values {
> +	A_SET_OF(ANY_t) list;
> +=09
> +	/* Context for parsing across buffer boundaries */
> +	asn_struct_ctx_t _asn_ctx;
> +} Values_t;
> +
> +/* Implementation */
> +extern asn_TYPE_descriptor_t asn_DEF_Values;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _Values_H_ */
> +#include <asn_internal.h>
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c
> b/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c new file mode 100644
> index 000000000000..ec952fc99936
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.c
> @@ -0,0 +1,41 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <asn_SEQUENCE_OF.h>
> +
> +typedef A_SEQUENCE_OF(void) asn_sequence;
> +
> +void
> +asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free) {
> +	asn_sequence *as =3D (asn_sequence *)asn_sequence_of_x;
> +
> +	if(as) {
> +		void *ptr;
> +		int n;
> +
> +		if(number < 0 || number >=3D as->count)
> +			return;	/* Nothing to delete */
> +
> +		if(_do_free && as->free) {
> +			ptr =3D as->array[number];
> +		} else {
> +			ptr =3D 0;
> +		}
> +
> +		/*
> +		 * Shift all elements to the left to hide the gap.
> +		 */
> +		--as->count;
> +		for(n =3D number; n < as->count; n++)
> +			as->array[n] =3D as->array[n+1];
> +
> +		/*
> +		 * Invoke the third-party function only when the
> state
> +		 * of the parent structure is consistent.
> +		 */
> +		if(ptr) as->free(ptr);
> +	}
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h
> b/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h new file mode 100644
> index 000000000000..e678f0347221
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_SEQUENCE_OF.h
> @@ -0,0 +1,52 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	ASN_SEQUENCE_OF_H
> +#define	ASN_SEQUENCE_OF_H
> +
> +#include <asn_SET_OF.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/*
> + * SEQUENCE OF is the same as SET OF with a tiny difference:
> + * the delete operation preserves the initial order of elements
> + * and thus MAY operate in non-constant time.
> + */
> +#define	A_SEQUENCE_OF(type)	A_SET_OF(type)
> +
> +#define	ASN_SEQUENCE_ADD(headptr, ptr)		\
> +	asn_sequence_add((headptr), (ptr))
> +
> +/***********************************************
> + * Implementation of the SEQUENCE OF structure.
> + */
> +
> +#define	asn_sequence_add	asn_set_add
> +#define	asn_sequence_empty	asn_set_empty
> +
> +/*
> + * Delete the element from the set by its number (base 0).
> + * This is NOT a constant-time operation.
> + * The order of elements is preserved.
> + * If _do_free is given AND the (*free) is initialized, the element
> + * will be freed using the custom (*free) function as well.
> + */
> +void asn_sequence_del(void *asn_sequence_of_x, int number, int
> _do_free); +
> +/*
> + * Cope with different conversions requirements to/from void in C
> and C++.
> + * This is mostly useful for support library.
> + */
> +typedef A_SEQUENCE_OF(void) asn_anonymous_sequence_;
> +#define _A_SEQUENCE_FROM_VOID(ptr)	((asn_anonymous_sequence_
> *)(ptr)) +#define _A_CSEQUENCE_FROM_VOID(ptr) 	((const
> asn_anonymous_sequence_ *)(ptr)) +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* ASN_SEQUENCE_OF_H */
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_SET_OF.c
> b/libkmod/pkcs7/asn1c-gen/asn_SET_OF.c new file mode 100644
> index 000000000000..944f2cb8ad70
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_SET_OF.c
> @@ -0,0 +1,88 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <asn_SET_OF.h>
> +#include <errno.h>
> +
> +/*
> + * Add another element into the set.
> + */
> +int
> +asn_set_add(void *asn_set_of_x, void *ptr) {
> +	asn_anonymous_set_ *as =3D _A_SET_FROM_VOID(asn_set_of_x);
> +
> +	if(as =3D=3D 0 || ptr =3D=3D 0) {
> +		errno =3D EINVAL;		/* Invalid arguments
> */
> +		return -1;
> +	}
> +
> +	/*
> +	 * Make sure there's enough space to insert an element.
> +	 */
> +	if(as->count =3D=3D as->size) {
> +		int _newsize =3D as->size ? (as->size << 1) : 4;
> +		void *_new_arr;
> +		_new_arr =3D REALLOC(as->array, _newsize *
> sizeof(as->array[0]));
> +		if(_new_arr) {
> +			as->array =3D (void **)_new_arr;
> +			as->size =3D _newsize;
> +		} else {
> +			/* ENOMEM */
> +			return -1;
> +		}
> +	}
> +
> +	as->array[as->count++] =3D ptr;
> +
> +	return 0;
> +}
> +
> +void
> +asn_set_del(void *asn_set_of_x, int number, int _do_free) {
> +	asn_anonymous_set_ *as =3D _A_SET_FROM_VOID(asn_set_of_x);
> +
> +	if(as) {
> +		void *ptr;
> +		if(number < 0 || number >=3D as->count)
> +			return;
> +
> +		if(_do_free && as->free) {
> +			ptr =3D as->array[number];
> +		} else {
> +			ptr =3D 0;
> +		}
> +
> +		as->array[number] =3D as->array[--as->count];
> +
> +		/*
> +		 * Invoke the third-party function only when the
> state
> +		 * of the parent structure is consistent.
> +		 */
> +		if(ptr) as->free(ptr);
> +	}
> +}
> +
> +/*
> + * Free the contents of the set, do not free the set itself.
> + */
> +void
> +asn_set_empty(void *asn_set_of_x) {
> +	asn_anonymous_set_ *as =3D _A_SET_FROM_VOID(asn_set_of_x);
> +
> +	if(as) {
> +		if(as->array) {
> +			if(as->free) {
> +				while(as->count--)
> +
> as->free(as->array[as->count]);
> +			}
> +			FREEMEM(as->array);
> +			as->array =3D 0;
> +		}
> +		as->count =3D 0;
> +		as->size =3D 0;
> +	}
> +
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_SET_OF.h
> b/libkmod/pkcs7/asn1c-gen/asn_SET_OF.h new file mode 100644
> index 000000000000..7edf14b51b98
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_SET_OF.h
> @@ -0,0 +1,62 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	ASN_SET_OF_H
> +#define	ASN_SET_OF_H
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#define	A_SET_OF(type)
> \
> +	struct {					\
> +		type **array;				\
> +		int count;	/* Meaningful size */	\
> +		int size;	/* Allocated size */	\
> +		void (*free)(type *);			\
> +	}
> +
> +#define	ASN_SET_ADD(headptr, ptr)		\
> +	asn_set_add((headptr), (ptr))
> +
> +/*******************************************
> + * Implementation of the SET OF structure.
> + */
> +
> +/*
> + * Add another structure into the set by its pointer.
> + * RETURN VALUES:
> + * 0 for success and -1/errno for failure.
> + */
> +int  asn_set_add(void *asn_set_of_x, void *ptr);
> +
> +/*
> + * Delete the element from the set by its number (base 0).
> + * This is a constant-time operation. The order of elements before
> the
> + * deleted ones is guaranteed, the order of elements after the
> deleted
> + * one is NOT guaranteed.
> + * If _do_free is given AND the (*free) is initialized, the element
> + * will be freed using the custom (*free) function as well.
> + */
> +void asn_set_del(void *asn_set_of_x, int number, int _do_free);
> +
> +/*
> + * Empty the contents of the set. Will free the elements, if (*free)
> is given.
> + * Will NOT free the set itself.
> + */
> +void asn_set_empty(void *asn_set_of_x);
> +
> +/*
> + * Cope with different conversions requirements to/from void in C
> and C++.
> + * This is mostly useful for support library.
> + */
> +typedef A_SET_OF(void) asn_anonymous_set_;
> +#define _A_SET_FROM_VOID(ptr)		((asn_anonymous_set_
> *)(ptr)) +#define _A_CSET_FROM_VOID(ptr)		((const
> asn_anonymous_set_ *)(ptr)) +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* ASN_SET_OF_H */
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_application.h
> b/libkmod/pkcs7/asn1c-gen/asn_application.h new file mode 100644
> index 000000000000..71e9ba61b2e8
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_application.h
> @@ -0,0 +1,47 @@
> +/*-
> + * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +/*
> + * Application-level ASN.1 callbacks.
> + */
> +#ifndef	ASN_APPLICATION_H
> +#define	ASN_APPLICATION_H
> +
> +#include "asn_system.h"		/* for platform-dependent
> types */ +#include "asn_codecs.h"		/* for ASN.1 codecs
> specifics */ +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/*
> + * Generic type of an application-defined callback to return various
> + * types of data to the application.
> + * EXPECTED RETURN VALUES:
> + *  -1: Failed to consume bytes. Abort the mission.
> + * Non-negative return values indicate success, and ignored.
> + */
> +typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t
> size,
> +	void *application_specific_key);
> +
> +/*
> + * A callback of this type is called whenever constraint validation
> fails
> + * on some ASN.1 type. See "constraints.h" for more details on
> constraint
> + * validation.
> + * This callback specifies a descriptor of the ASN.1 type which
> failed
> + * the constraint check, as well as human readable message on what
> + * particular constraint has failed.
> + */
> +typedef void (asn_app_constraint_failed_f)(void
> *application_specific_key,
> +	struct asn_TYPE_descriptor_s *type_descriptor_which_failed,
> +	const void *structure_which_failed_ptr,
> +	const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#include "constr_TYPE.h"	/* for asn_TYPE_descriptor_t */
> +
> +#endif	/* ASN_APPLICATION_H */
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_codecs.h
> b/libkmod/pkcs7/asn1c-gen/asn_codecs.h new file mode 100644
> index 000000000000..4b2a294293c2
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_codecs.h
> @@ -0,0 +1,109 @@
> +/*-
> + * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
> + * All rights reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	ASN_CODECS_H
> +#define	ASN_CODECS_H
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +struct asn_TYPE_descriptor_s;	/* Forward declaration */
> +
> +/*
> + * This structure defines a set of parameters that may be passed
> + * to every ASN.1 encoder or decoder function.
> + * WARNING: if max_stack_size member is set, and you are calling the
> + *   function pointers of the asn_TYPE_descriptor_t directly,
> + *   this structure must be ALLOCATED ON THE STACK!
> + *   If you can't always satisfy this requirement, use ber_decode(),
> + *   xer_decode() and uper_decode() functions instead.
> + */
> +typedef struct asn_codec_ctx_s {
> +	/*
> +	 * Limit the decoder routines to use no (much) more stack
> than a given
> +	 * number of bytes. Most of decoders are stack-based, and
> this
> +	 * would protect against stack overflows if the number of
> nested
> +	 * encodings is high.
> +	 * The OCTET STRING, BIT STRING and ANY BER decoders are
> heap-based,
> +	 * and are safe from this kind of overflow.
> +	 * A value from getrlimit(RLIMIT_STACK) may be used to
> initialize
> +	 * this variable. Be careful in multithreaded environments,
> as the
> +	 * stack size is rather limited.
> +	 */
> +	size_t  max_stack_size; /* 0 disables stack bounds checking
> */ +} asn_codec_ctx_t;
> +
> +/*
> + * Type of the return value of the encoding functions (der_encode,
> xer_encode).
> + */
> +typedef struct asn_enc_rval_s {
> +	/*
> +	 * Number of bytes encoded.
> +	 * -1 indicates failure to encode the structure.
> +	 * In this case, the members below this one are meaningful.
> +	 */
> +	ssize_t encoded;
> +
> +	/*
> +	 * Members meaningful when (encoded =3D=3D -1), for post mortem
> analysis.
> +	 */
> +
> +	/* Type which cannot be encoded */
> +	struct asn_TYPE_descriptor_s *failed_type;
> +
> +	/* Pointer to the structure of that type */
> +	void *structure_ptr;
> +} asn_enc_rval_t;
> +#define	ASN__ENCODE_FAILED do
> {					\
> +	asn_enc_rval_t tmp_error;				\
> +	tmp_error.encoded =3D
> -1;					\
> +	tmp_error.failed_type =3D td;				\
> +	tmp_error.structure_ptr =3D
> sptr;				\
> +	ASN_DEBUG("Failed to encode element %s", td ? td->name :
> "");	\
> +	return tmp_error;					\
> +} while(0)
> +#define	ASN__ENCODED_OK(rval) do
> {				\
> +	rval.structure_ptr =3D
> 0;					\
> +	rval.failed_type =3D 0;
> \
> +	return rval;						\
> +} while(0)
> +
> +/*
> + * Type of the return value of the decoding functions (ber_decode,
> xer_decode)
> + *=20
> + * Please note that the number of consumed bytes is ALWAYS
> meaningful,
> + * even if code=3D=3DRC_FAIL. This is to indicate the number of
> successfully
> + * decoded bytes, hence providing a possibility to fail with more
> diagnostics
> + * (i.e., print the offending remainder of the buffer).
> + */
> +enum asn_dec_rval_code_e {
> +	RC_OK,		/* Decoded successfully */
> +	RC_WMORE,	/* More data expected, call again */
> +	RC_FAIL		/* Failure to decode data */
> +};
> +typedef struct asn_dec_rval_s {
> +	enum asn_dec_rval_code_e code;	/* Result code */
> +	size_t consumed;		/* Number of bytes consumed
> */ +} asn_dec_rval_t;
> +#define	ASN__DECODE_FAILED do
> {					\
> +	asn_dec_rval_t tmp_error;				\
> +	tmp_error.code =3D RC_FAIL;				\
> +	tmp_error.consumed =3D
> 0;					\
> +	ASN_DEBUG("Failed to decode element %s", td ? td->name :
> "");	\
> +	return tmp_error;					\
> +} while(0)
> +#define	ASN__DECODE_STARVED do
> {				\
> +	asn_dec_rval_t tmp_error;				\
> +	tmp_error.code =3D RC_WMORE;				\
> +	tmp_error.consumed =3D
> 0;					\
> +	return tmp_error;					\
> +} while(0)
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* ASN_CODECS_H */
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c
> b/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c new file mode 100644
> index 000000000000..426339c94fa9
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.c
> @@ -0,0 +1,312 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <asn_codecs_prim.h>
> +#include <errno.h>
> +
> +/*
> + * Decode an always-primitive type.
> + */
> +asn_dec_rval_t
> +ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td,
> +	void **sptr, const void *buf_ptr, size_t size, int tag_mode)
> {
> +	ASN__PRIMITIVE_TYPE_t *st =3D (ASN__PRIMITIVE_TYPE_t *)*sptr;
> +	asn_dec_rval_t rval;
> +	ber_tlv_len_t length =3D 0; /* =3D0 to avoid [incorrect]
> warning. */ +
> +	/*
> +	 * If the structure is not there, allocate it.
> +	 */
> +	if(st =3D=3D NULL) {
> +		st =3D (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
> +		if(st =3D=3D NULL) ASN__DECODE_FAILED;
> +		*sptr =3D (void *)st;
> +	}
> +
> +	ASN_DEBUG("Decoding %s as plain primitive (tm=3D%d)",
> +		td->name, tag_mode);
> +
> +	/*
> +	 * Check tags and extract value length.
> +	 */
> +	rval =3D ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
> +			tag_mode, 0, &length, 0);
> +	if(rval.code !=3D RC_OK)
> +		return rval;
> +
> +	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
> +
> +	/*
> +	 * Make sure we have this length.
> +	 */
> +	buf_ptr =3D ((const char *)buf_ptr) + rval.consumed;
> +	size -=3D rval.consumed;
> +	if(length > (ber_tlv_len_t)size) {
> +		rval.code =3D RC_WMORE;
> +		rval.consumed =3D 0;
> +		return rval;
> +	}
> +
> +	st->size =3D (int)length;
> +	/* The following better be optimized away. */
> +	if(sizeof(st->size) !=3D sizeof(length)
> +			&& (ber_tlv_len_t)st->size !=3D length) {
> +		st->size =3D 0;
> +		ASN__DECODE_FAILED;
> +	}
> +
> +	st->buf =3D (uint8_t *)MALLOC(length + 1);
> +	if(!st->buf) {
> +		st->size =3D 0;
> +		ASN__DECODE_FAILED;
> +	}
> +
> +	memcpy(st->buf, buf_ptr, length);
> +	st->buf[length] =3D '\0';		/* Just in case */
> +
> +	rval.code =3D RC_OK;
> +	rval.consumed +=3D length;
> +
> +	ASN_DEBUG("Took %ld/%ld bytes to encode %s",
> +		(long)rval.consumed,
> +		(long)length, td->name);
> +
> +	return rval;
> +}
> +
> +/*
> + * Encode an always-primitive type using DER.
> + */
> +asn_enc_rval_t
> +der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
> +	int tag_mode, ber_tlv_tag_t tag,
> +	asn_app_consume_bytes_f *cb, void *app_key) {
> +	asn_enc_rval_t erval;
> +	ASN__PRIMITIVE_TYPE_t *st =3D (ASN__PRIMITIVE_TYPE_t *)sptr;
> +
> +	ASN_DEBUG("%s %s as a primitive type (tm=3D%d)",
> +		cb?"Encoding":"Estimating", td->name, tag_mode);
> +
> +	erval.encoded =3D der_write_tags(td, st->size, tag_mode, 0,
> tag,
> +		cb, app_key);
> +	ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
> +	if(erval.encoded =3D=3D -1) {
> +		erval.failed_type =3D td;
> +		erval.structure_ptr =3D sptr;
> +		return erval;
> +	}
> +
> +	if(cb && st->buf) {
> +		if(cb(st->buf, st->size, app_key) < 0) {
> +			erval.encoded =3D -1;
> +			erval.failed_type =3D td;
> +			erval.structure_ptr =3D sptr;
> +			return erval;
> +		}
> +	} else {
> +		assert(st->buf || st->size =3D=3D 0);
> +	}
> +
> +	erval.encoded +=3D st->size;
> +	ASN__ENCODED_OK(erval);
> +}
> +
> +void
> +ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
> +		int contents_only) {
> +	ASN__PRIMITIVE_TYPE_t *st =3D (ASN__PRIMITIVE_TYPE_t *)sptr;
> +
> +	if(!td || !sptr)
> +		return;
> +
> +	ASN_DEBUG("Freeing %s as a primitive type", td->name);
> +
> +	if(st->buf)
> +		FREEMEM(st->buf);
> +
> +	if(!contents_only)
> +		FREEMEM(st);
> +}
> +
> +
> +/*
> + * Local internal type passed around as an argument.
> + */
> +struct xdp_arg_s {
> +	asn_TYPE_descriptor_t *type_descriptor;
> +	void *struct_key;
> +	xer_primitive_body_decoder_f *prim_body_decoder;
> +	int decoded_something;
> +	int want_more;
> +};
> +
> +/*
> + * Since some kinds of primitive values can be encoded using
> value-specific
> + * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive
> decoder must
> + * be supplied with such tags to parse them as needed.
> + */
> +static int
> +xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t
> chunk_size) {
> +	struct xdp_arg_s *arg =3D (struct xdp_arg_s *)key;
> +	enum xer_pbd_rval bret;
> +
> +	/*
> +	 * The chunk_buf is guaranteed to start at '<'.
> +	 */
> +	assert(chunk_size && ((const char *)chunk_buf)[0] =3D=3D 0x3c);
> +
> +	/*
> +	 * Decoding was performed once already. Prohibit doing it
> again.
> +	 */
> +	if(arg->decoded_something)
> +		return -1;
> +
> +	bret =3D arg->prim_body_decoder(arg->type_descriptor,
> +		arg->struct_key, chunk_buf, chunk_size);
> +	switch(bret) {
> +	case XPBD_SYSTEM_FAILURE:
> +	case XPBD_DECODER_LIMIT:
> +	case XPBD_BROKEN_ENCODING:
> +		break;
> +	case XPBD_BODY_CONSUMED:
> +		/* Tag decoded successfully */
> +		arg->decoded_something =3D 1;
> +		/* Fall through */
> +	case XPBD_NOT_BODY_IGNORE:	/* Safe to proceed further
> */
> +		return 0;
> +	}
> +
> +	return -1;
> +}
> +
> +static ssize_t
> +xer_decode__primitive_body(void *key, const void *chunk_buf, size_t
> chunk_size, int have_more) {
> +	struct xdp_arg_s *arg =3D (struct xdp_arg_s *)key;
> +	enum xer_pbd_rval bret;
> +	size_t lead_wsp_size;
> +
> +	if(arg->decoded_something) {
> +		if(xer_whitespace_span(chunk_buf, chunk_size) =3D=3D
> chunk_size) {
> +			/*
> +			 * Example:
> +			 * "<INTEGER>123<!--/--> </INTEGER>"
> +			 *                      ^- chunk_buf
> position.
> +			 */
> +			return chunk_size;
> +		}
> +		/*
> +		 * Decoding was done once already. Prohibit doing it
> again.
> +		 */
> +		return -1;
> +	}
> +
> +	if(!have_more) {
> +		/*
> +		 * If we've received something like "1", we can't
> really
> +		 * tell whether it is really `1` or `123`, until we
> know
> +		 * that there is no more data coming.
> +		 * The have_more argument will be set to 1 once
> something
> +		 * like this is available to the caller of this
> callback:
> +		 * "1<tag_start..."
> +		 */
> +		arg->want_more =3D 1;
> +		return -1;
> +	}
> +
> +	lead_wsp_size =3D xer_whitespace_span(chunk_buf, chunk_size);
> +	chunk_buf =3D (const char *)chunk_buf + lead_wsp_size;
> +	chunk_size -=3D lead_wsp_size;
> +
> +	bret =3D arg->prim_body_decoder(arg->type_descriptor,
> +		arg->struct_key, chunk_buf, chunk_size);
> +	switch(bret) {
> +	case XPBD_SYSTEM_FAILURE:
> +	case XPBD_DECODER_LIMIT:
> +	case XPBD_BROKEN_ENCODING:
> +		break;
> +	case XPBD_BODY_CONSUMED:
> +		/* Tag decoded successfully */
> +		arg->decoded_something =3D 1;
> +		/* Fall through */
> +	case XPBD_NOT_BODY_IGNORE:	/* Safe to proceed further
> */
> +		return lead_wsp_size + chunk_size;
> +	}
> +
> +	return -1;
> +}
> +
> +
> +asn_dec_rval_t
> +xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *td,
> +	void **sptr,
> +	size_t struct_size,
> +	const char *opt_mname,
> +	const void *buf_ptr, size_t size,
> +	xer_primitive_body_decoder_f *prim_body_decoder
> +) {
> +	const char *xml_tag =3D opt_mname ? opt_mname : td->xml_tag;
> +	asn_struct_ctx_t s_ctx;
> +	struct xdp_arg_s s_arg;
> +	asn_dec_rval_t rc;
> +
> +	/*
> +	 * Create the structure if does not exist.
> +	 */
> +	if(!*sptr) {
> +		*sptr =3D CALLOC(1, struct_size);
> +		if(!*sptr) ASN__DECODE_FAILED;
> +	}
> +
> +	memset(&s_ctx, 0, sizeof(s_ctx));
> +	s_arg.type_descriptor =3D td;
> +	s_arg.struct_key =3D *sptr;
> +	s_arg.prim_body_decoder =3D prim_body_decoder;
> +	s_arg.decoded_something =3D 0;
> +	s_arg.want_more =3D 0;
> +
> +	rc =3D xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
> +		xml_tag, buf_ptr, size,
> +		xer_decode__unexpected_tag,
> xer_decode__primitive_body);
> +	switch(rc.code) {
> +	case RC_OK:
> +		if(!s_arg.decoded_something) {
> +			char ch;
> +			ASN_DEBUG("Primitive body is not recognized,
> "
> +				"supplying empty one");
> +			/*
> +			 * Decoding opportunity has come and gone.
> +			 * Where's the result?
> +			 * Try to feed with empty body, see if it
> eats it.
> +			 */
> +			if(prim_body_decoder(s_arg.type_descriptor,
> +				s_arg.struct_key, &ch, 0)
> +					!=3D XPBD_BODY_CONSUMED) {
> +				/*
> +				 * This decoder does not like empty
> stuff.
> +				 */
> +				ASN__DECODE_FAILED;
> +			}
> +		}
> +		break;
> +	case RC_WMORE:
> +		/*
> +		 * Redo the whole thing later.
> +		 * We don't have a context to save intermediate
> parsing state.
> +		 */
> +		rc.consumed =3D 0;
> +		break;
> +	case RC_FAIL:
> +		rc.consumed =3D 0;
> +		if(s_arg.want_more)
> +			rc.code =3D RC_WMORE;
> +		else
> +			ASN__DECODE_FAILED;
> +		break;
> +	}
> +	return rc;
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h
> b/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h new file mode 100644
> index 000000000000..0f683fdd0ac7
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_codecs_prim.h
> @@ -0,0 +1,53 @@
> +/*-
> + * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	ASN_CODECS_PRIM_H
> +#define	ASN_CODECS_PRIM_H
> +
> +#include <asn_application.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef struct ASN__PRIMITIVE_TYPE_s {
> +	uint8_t *buf;	/* Buffer with consecutive primitive
> encoding bytes */
> +	int size;	/* Size of the buffer */
> +} ASN__PRIMITIVE_TYPE_t;	/* Do not use this type directly! */
> +
> +asn_struct_free_f ASN__PRIMITIVE_TYPE_free;
> +ber_type_decoder_f ber_decode_primitive;
> +der_type_encoder_f der_encode_primitive;
> +
> +/*
> + * A callback specification for the xer_decode_primitive() function
> below.
> + */
> +enum xer_pbd_rval {
> +	XPBD_SYSTEM_FAILURE,	/* System failure (memory
> shortage, etc) */
> +	XPBD_DECODER_LIMIT,	/* Hit some decoder limitation or
> deficiency */
> +	XPBD_BROKEN_ENCODING,	/* Encoding of a primitive body
> is broken */
> +	XPBD_NOT_BODY_IGNORE,	/* Not a body format, but safe
> to ignore */
> +	XPBD_BODY_CONSUMED	/* Body is recognized and consumed
> */ +};
> +typedef enum xer_pbd_rval (xer_primitive_body_decoder_f)
> +	(asn_TYPE_descriptor_t *td, void *struct_ptr,
> +		const void *chunk_buf, size_t chunk_size);
> +
> +/*
> + * Specific function to decode simple primitive types.
> + * Also see xer_decode_general() in xer_decoder.h
> + */
> +asn_dec_rval_t xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *type_descriptor,
> +	void **struct_ptr, size_t struct_size,
> +	const char *opt_mname,
> +	const void *buf_ptr, size_t size,
> +	xer_primitive_body_decoder_f *prim_body_decoder
> +);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* ASN_CODECS_PRIM_H */
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_internal.h
> b/libkmod/pkcs7/asn1c-gen/asn_internal.h new file mode 100644
> index 000000000000..9c94ca6c3b77
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_internal.h
> @@ -0,0 +1,128 @@
> +/*-
> + * Copyright (c) 2003, 2004, 2005, 2007 Lev Walkin <vlm@lionet.info>.
> + * All rights reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +/*
> + * Declarations internally useful for the ASN.1 support code.
> + */
> +#ifndef	ASN_INTERNAL_H
> +#define	ASN_INTERNAL_H
> +
> +#include "asn_application.h"	/* Application-visible API */
> +
> +#ifndef	__NO_ASSERT_H__		/* Include assert.h
> only for internal use. */ +#include <assert.h>		/* for
> assert() macro */ +#endif
> +
> +#ifdef	__cplusplus
> +extern "C" {
> +#endif
> +
> +/* Environment version might be used to avoid running with the old
> library */ +#define	ASN1C_ENVIRONMENT_VERSION
> 923	/* Compile-time version */ +int
> get_asn1c_environment_version(void);	/* Run-time version */ +
> +#define	CALLOC(nmemb, size)	calloc(nmemb, size)
> +#define	MALLOC(size)		malloc(size)
> +#define	REALLOC(oldptr, size)	realloc(oldptr, size)
> +#define	FREEMEM(ptr)		free(ptr)
> +
> +#define	asn_debug_indent	0
> +#define ASN_DEBUG_INDENT_ADD(i) do{}while(0)
> +
> +/*
> + * A macro for debugging the ASN.1 internals.
> + * You may enable or override it.
> + */
> +#ifndef	ASN_DEBUG	/* If debugging code is not defined
> elsewhere... */ +#if	EMIT_ASN_DEBUG =3D=3D 1	/* And it was
> asked to emit this code... */ +#ifdef	__GNUC__
> +#ifdef	ASN_THREAD_SAFE
> +/* Thread safety requires sacrifice in output indentation:
> + * Retain empty definition of ASN_DEBUG_INDENT_ADD. */
> +#else	/* !ASN_THREAD_SAFE */
> +#undef  ASN_DEBUG_INDENT_ADD
> +#undef  asn_debug_indent
> +int asn_debug_indent;
> +#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent +=3D i; }
> while(0) +#endif	/* ASN_THREAD_SAFE */
> +#define	ASN_DEBUG(fmt, args...)	do
> {			\
> +		int adi =3D asn_debug_indent;		\
> +		while(adi--) fprintf(stderr, " ");	\
> +		fprintf(stderr, fmt, ##args);		\
> +		fprintf(stderr, " (%s:%d)\n",		\
> +			__FILE__, __LINE__);		\
> +	} while(0)
> +#else	/* !__GNUC__ */
> +void ASN_DEBUG_f(const char *fmt, ...);
> +#define	ASN_DEBUG	ASN_DEBUG_f
> +#endif	/* __GNUC__ */
> +#else	/* EMIT_ASN_DEBUG !=3D 1 */
> +static void ASN_DEBUG(const char *fmt, ...) { (void)fmt; }
> +#endif	/* EMIT_ASN_DEBUG */
> +#endif	/* ASN_DEBUG */
> +
> +/*
> + * Invoke the application-supplied callback and fail, if something
> is wrong.
> + */
> +#define	ASN__E_cbc(buf, size)	(cb((buf), (size),
> app_key) < 0) +#define	ASN__E_CALLBACK(foo)	do
> {					\
> +		if(foo)	goto
> cb_failed;					\
> +	} while(0)
> +#define	ASN__CALLBACK(buf,
> size)					\
> +	ASN__E_CALLBACK(ASN__E_cbc(buf, size))
> +#define	ASN__CALLBACK2(buf1, size1, buf2,
> size2)			\
> +	ASN__E_CALLBACK(ASN__E_cbc(buf1, size1) || ASN__E_cbc(buf2,
> size2)) +#define	ASN__CALLBACK3(buf1, size1, buf2, size2,
> buf3, size3)		\
> +	ASN__E_CALLBACK(ASN__E_cbc(buf1,
> size1)			\
> +		|| ASN__E_cbc(buf2,
> size2)				\
> +		|| ASN__E_cbc(buf3, size3))
> +
> +#define	ASN__TEXT_INDENT(nl, level) do {            \
> +        int tmp_level =3D (level);                    \
> +        int tmp_nl =3D ((nl) !=3D 0);                   \
> +        int tmp_i;                                  \
> +        if(tmp_nl) ASN__CALLBACK("\n", 1);          \
> +        if(tmp_level < 0) tmp_level =3D 0;            \
> +        for(tmp_i =3D 0; tmp_i < tmp_level; tmp_i++)  \
> +            ASN__CALLBACK("    ", 4);               \
> +        er.encoded +=3D tmp_nl + 4 * tmp_level;       \
> +    } while(0)
> +
> +#define	_i_INDENT(nl)	do {                        \
> +        int tmp_i;                                  \
> +        if((nl) && cb("\n", 1, app_key) < 0)        \
> +            return -1;                              \
> +        for(tmp_i =3D 0; tmp_i < ilevel; tmp_i++)     \
> +            if(cb("    ", 4, app_key) < 0)          \
> +                return -1;                          \
> +    } while(0)
> +
> +/*
> + * Check stack against overflow, if limit is set.
> + */
> +#define	ASN__DEFAULT_STACK_MAX	(30000)
> +static int __attribute__((unused))
> +ASN__STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) {
> +	if(ctx && ctx->max_stack_size) {
> +
> +		/* ctx MUST be allocated on the stack */
> +		ptrdiff_t usedstack =3D ((char *)ctx - (char *)&ctx);
> +		if(usedstack > 0) usedstack =3D -usedstack; /* grows
> up! */ +
> +		/* double negative required to avoid int wrap-around
> */
> +		if(usedstack < -(ptrdiff_t)ctx->max_stack_size) {
> +			ASN_DEBUG("Stack limit %ld reached",
> +				(long)ctx->max_stack_size);
> +			return -1;
> +		}
> +	}
> +	return 0;
> +}
> +
> +#ifdef	__cplusplus
> +}
> +#endif
> +
> +#endif	/* ASN_INTERNAL_H */
> diff --git a/libkmod/pkcs7/asn1c-gen/asn_system.h
> b/libkmod/pkcs7/asn1c-gen/asn_system.h new file mode 100644
> index 000000000000..d19837edf59e
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/asn_system.h
> @@ -0,0 +1,137 @@
> +/*-
> + * Copyright (c) 2003, 2004, 2007 Lev Walkin <vlm@lionet.info>.
> + * All rights reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +/*
> + * Miscellaneous system-dependent types.
> + */
> +#ifndef	ASN_SYSTEM_H
> +#define	ASN_SYSTEM_H
> +
> +#ifdef	HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#ifndef _BSD_SOURCE
> +#define _BSD_SOURCE /* for snprintf() on some linux systems  */
> +#endif
> +
> +#include <stdio.h>	/* For snprintf(3) */
> +#include <stdlib.h>	/* For *alloc(3) */
> +#include <string.h>	/* For memcpy(3) */
> +#include <sys/types.h>	/* For size_t */
> +#include <limits.h>	/* For LONG_MAX */
> +#include <stdarg.h>	/* For va_start */
> +#include <stddef.h>	/* for offsetof and ptrdiff_t */
> +
> +#ifdef	HAVE_ALLOCA_H
> +#include <alloca.h>	/* For alloca(3) */
> +#endif
> +
> +#ifdef	_WIN32
> +
> +#include <malloc.h>
> +#define	 snprintf	_snprintf
> +#define	 vsnprintf	_vsnprintf
> +
> +/* To avoid linking with ws2_32.lib, here's the definition of
> ntohl() */ +#define sys_ntohl(l)	((((l) << 24)  &
> 0xff000000)	\
> +			| (((l) << 8) & 0xff0000)	\
> +			| (((l) >> 8)  & 0xff00)	\
> +			| ((l >> 24) & 0xff))
> +
> +#ifdef _MSC_VER			/* MSVS.Net */
> +#ifndef __cplusplus
> +#define inline __inline
> +#endif
> +#ifndef	ASSUMESTDTYPES	/* Standard types have been
> defined elsewhere */ +#define	ssize_t		SSIZE_T
> +typedef	char		int8_t;
> +typedef	short		int16_t;
> +typedef	int		int32_t;
> +typedef	unsigned char	uint8_t;
> +typedef	unsigned short	uint16_t;
> +typedef	unsigned int	uint32_t;
> +#endif	/* ASSUMESTDTYPES */
> +#define WIN32_LEAN_AND_MEAN
> +#include <windows.h>
> +#include <float.h>
> +#define isnan _isnan
> +#define finite _finite
> +#define copysign _copysign
> +#define	ilogb	_logb
> +#else	/* !_MSC_VER */
> +#include <stdint.h>
> +#endif	/* _MSC_VER */
> +
> +#else	/* !_WIN32 */
> +
> +#if defined(__vxworks)
> +#include <types/vxTypes.h>
> +#else	/* !defined(__vxworks) */
> +
> +#include <inttypes.h>	/* C99 specifies this file */
> +/*
> + * 1. Earlier FreeBSD version didn't have <stdint.h>,
> + * but <inttypes.h> was present.
> + * 2. Sun Solaris requires <alloca.h> for alloca(3),
> + * but does not have <stdint.h>.
> + */
> +#if	(!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_))
> +#if	defined(sun)
> +#include <alloca.h>	/* For alloca(3) */
> +#include <ieeefp.h>	/* for finite(3) */
> +#elif	defined(__hpux)
> +#ifdef	__GNUC__
> +#include <alloca.h>	/* For alloca(3) */
> +#else	/* !__GNUC__ */
> +#define inline
> +#endif	/* __GNUC__ */
> +#else
> +#include <stdint.h>	/* SUSv2+ and C99 specify this file, for
> uintXX_t */ +#endif	/* defined(sun) */
> +#endif
> +
> +#include <netinet/in.h> /* for ntohl() */
> +#define	sys_ntohl(foo)	ntohl(foo)
> +
> +#endif	/* defined(__vxworks) */
> +
> +#endif	/* _WIN32 */
> +
> +#if	__GNUC__ >=3D 3
> +#ifndef	GCC_PRINTFLIKE
> +#define	GCC_PRINTFLIKE(fmt,var)
> __attribute__((format(printf,fmt,var))) +#endif
> +#ifndef	GCC_NOTUSED
> +#define	GCC_NOTUSED		__attribute__((unused))
> +#endif
> +#else
> +#ifndef	GCC_PRINTFLIKE
> +#define	GCC_PRINTFLIKE(fmt,var)	/* nothing */
> +#endif
> +#ifndef	GCC_NOTUSED
> +#define	GCC_NOTUSED
> +#endif
> +#endif
> +
> +/* Figure out if thread safety is requested */
> +#if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) ||
> defined(_REENTRANT)) +#define	ASN_THREAD_SAFE
> +#endif	/* Thread safety */
> +
> +#ifndef	offsetof	/* If not defined by <stddef.h> */
> +#define	offsetof(s, m)	((ptrdiff_t)&(((s *)0)->m) -
> (ptrdiff_t)((s *)0)) +#endif	/* offsetof */
> +
> +#ifndef	MIN		/* Suitable for comparing
> primitive types (integers) */ +#if defined(__GNUC__)
> +#define	MIN(a,b)	({ __typeof a _a =3D a; __typeof b _b =3D
> b;	\
> +	((_a)<(_b)?(_a):(_b)); })
> +#else	/* !__GNUC__ */
> +#define	MIN(a,b)	((a)<(b)?(a):(b))	/* Unsafe
> variant */ +#endif /* __GNUC__ */
> +#endif	/* MIN */
> +
> +#endif	/* ASN_SYSTEM_H */
> diff --git a/libkmod/pkcs7/asn1c-gen/ber_decoder.c
> b/libkmod/pkcs7/asn1c-gen/ber_decoder.c new file mode 100644
> index 000000000000..b3a6329e063f
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ber_decoder.c
> @@ -0,0 +1,283 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +
> +#undef	ADVANCE
> +#define	ADVANCE(num_bytes)	do
> {					\
> +		size_t num =3D
> num_bytes;					\
> +		ptr =3D ((const char *)ptr) +
> num;			\
> +		size -=3D
> num;						\
> +		consumed_myself +=3D
> num;					\
> +	} while(0)
> +#undef	RETURN
> +#define	RETURN(_code)	do
> {						\
> +		asn_dec_rval_t
> rval;					\
> +		rval.code =3D
> _code;					\
> +		if(opt_ctx) opt_ctx->step =3D step; /* Save context
> */	\
> +		if(_code =3D=3D RC_OK ||
> opt_ctx)				\
> +			rval.consumed =3D
> consumed_myself;		\
> +
> else							\
> +			rval.consumed =3D 0;	/* Context-free
> */	\
> +		return
> rval;						\
> +	} while(0)
> +
> +/*
> + * The BER decoder of any type.
> + */
> +asn_dec_rval_t
> +ber_decode(asn_codec_ctx_t *opt_codec_ctx,
> +	asn_TYPE_descriptor_t *type_descriptor,
> +	void **struct_ptr, const void *ptr, size_t size) {
> +	asn_codec_ctx_t s_codec_ctx;
> +
> +	/*
> +	 * Stack checker requires that the codec context
> +	 * must be allocated on the stack.
> +	 */
> +	if(opt_codec_ctx) {
> +		if(opt_codec_ctx->max_stack_size) {
> +			s_codec_ctx =3D *opt_codec_ctx;
> +			opt_codec_ctx =3D &s_codec_ctx;
> +		}
> +	} else {
> +		/* If context is not given, be security-conscious
> anyway */
> +		memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
> +		s_codec_ctx.max_stack_size =3D ASN__DEFAULT_STACK_MAX;
> +		opt_codec_ctx =3D &s_codec_ctx;
> +	}
> +
> +	/*
> +	 * Invoke type-specific decoder.
> +	 */
> +	return type_descriptor->ber_decoder(opt_codec_ctx,
> type_descriptor,
> +		struct_ptr,	/* Pointer to the destination
> structure */
> +		ptr, size,	/* Buffer and its size */
> +		0		/* Default tag mode is 0 */
> +		);
> +}
> +
> +/*
> + * Check the set of <TL<TL<TL...>>> tags matches the definition.
> + */
> +asn_dec_rval_t
> +ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
> +		asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx,
> +		const void *ptr, size_t size, int tag_mode, int
> last_tag_form,
> +		ber_tlv_len_t *last_length, int *opt_tlv_form) {
> +	ssize_t consumed_myself =3D 0;
> +	ssize_t tag_len;
> +	ssize_t len_len;
> +	ber_tlv_tag_t tlv_tag;
> +	ber_tlv_len_t tlv_len;
> +	ber_tlv_len_t limit_len =3D -1;
> +	int expect_00_terminators =3D 0;
> +	int tlv_constr =3D -1;	/* If CHOICE, opt_tlv_form is
> not given */
> +	int step =3D opt_ctx ? opt_ctx->step : 0;	/* Where we
> left previously */
> +	int tagno;
> +
> +	/*
> +	 * Make sure we didn't exceed the maximum stack size.
> +	 */
> +	if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
> +		RETURN(RC_FAIL);
> +
> +	/*
> +	 * So what does all this implicit skip stuff mean?
> +	 * Imagine two types,
> +	 * 	A ::=3D [5] IMPLICIT	T
> +	 * 	B ::=3D [2] EXPLICIT	T
> +	 * Where T is defined as
> +	 *	T ::=3D [4] IMPLICIT SEQUENCE { ... }
> +	 *=20
> +	 * Let's say, we are starting to decode type A, given the
> +	 * following TLV stream: <5> <0>. What does this mean?
> +	 * It means that the type A contains type T which is,
> +	 * in turn, empty.
> +	 * Remember though, that we are still in A. We cannot
> +	 * just pass control to the type T decoder. Why? Because
> +	 * the type T decoder expects <4> <0>, not <5> <0>.
> +	 * So, we must make sure we are going to receive <5> while
> +	 * still in A, then pass control to the T decoder, indicating
> +	 * that the tag <4> was implicitly skipped. The decoder of T
> +	 * hence will be prepared to treat <4> as valid tag, and
> decode
> +	 * it appropriately.
> +	 */
> +
> +	tagno =3D step	/* Continuing where left previously */
> +		+ (tag_mode=3D=3D1?-1:0)
> +		;
> +	ASN_DEBUG("ber_check_tags(%s, size=3D%ld, tm=3D%d, step=3D%d,
> tagno=3D%d)",
> +		td->name, (long)size, tag_mode, step, tagno);
> +	/* assert(td->tags_count >=3D 1) May not be the case for
> CHOICE or ANY */ +
> +	if(tag_mode =3D=3D 0 && tagno =3D=3D td->tags_count) {
> +		/*
> +		 * This must be the _untagged_ ANY type,
> +		 * which outermost tag isn't known in advance.
> +		 * Fetch the tag and length separately.
> +		 */
> +		tag_len =3D ber_fetch_tag(ptr, size, &tlv_tag);
> +		switch(tag_len) {
> +		case -1: RETURN(RC_FAIL);
> +		case 0: RETURN(RC_WMORE);
> +		}
> +		tlv_constr =3D BER_TLV_CONSTRUCTED(ptr);
> +		len_len =3D ber_fetch_length(tlv_constr,
> +			(const char *)ptr + tag_len, size - tag_len,
> &tlv_len);
> +		switch(len_len) {
> +		case -1: RETURN(RC_FAIL);
> +		case 0: RETURN(RC_WMORE);
> +		}
> +		ASN_DEBUG("Advancing %ld in ANY case",
> +			(long)(tag_len + len_len));
> +		ADVANCE(tag_len + len_len);
> +	} else {
> +		assert(tagno < td->tags_count);	/* At least
> one loop */
> +	}
> +	for((void)tagno; tagno < td->tags_count; tagno++, step++) {
> +
> +		/*
> +		 * Fetch and process T from TLV.
> +		 */
> +		tag_len =3D ber_fetch_tag(ptr, size, &tlv_tag);
> +			ASN_DEBUG("Fetching tag from {%p,%ld}: "
> +				"len %ld, step %d, tagno %d got %s",
> +				ptr, (long)size,
> +				(long)tag_len, step, tagno,
> +				ber_tlv_tag_string(tlv_tag));
> +		switch(tag_len) {
> +		case -1: RETURN(RC_FAIL);
> +		case 0: RETURN(RC_WMORE);
> +		}
> +
> +		tlv_constr =3D BER_TLV_CONSTRUCTED(ptr);
> +
> +		/*
> +		 * If {I}, don't check anything.
> +		 * If {I,B,C}, check B and C unless we're at I.
> +		 */
> +		if(tag_mode !=3D 0 && step =3D=3D 0) {
> +			/*
> +			 * We don't expect tag to match here.
> +			 * It's just because we don't know how the
> tag
> +			 * is supposed to look like.
> +			 */
> +		} else {
> +		    assert(tagno >=3D 0);	/* Guaranteed by the
> code above */
> +		    if(tlv_tag !=3D td->tags[tagno]) {
> +			/*
> +			 * Unexpected tag. Too bad.
> +			 */
> +		    	ASN_DEBUG("Expected: %s, "
> +				"expectation failed (tn=3D%d, tm=3D%d)",
> +				ber_tlv_tag_string(td->tags[tagno]),
> +				tagno, tag_mode
> +			);
> +			RETURN(RC_FAIL);
> +		    }
> +		}
> +
> +		/*
> +		 * Attention: if there are more tags expected,
> +		 * ensure that the current tag is presented
> +		 * in constructed form (it contains other tags!).
> +		 * If this one is the last one, check that the tag
> form
> +		 * matches the one given in descriptor.
> +		 */
> +		if(tagno < (td->tags_count - 1)) {
> +			if(tlv_constr =3D=3D 0) {
> +				ASN_DEBUG("tlv_constr =3D %d, expfail",
> +					tlv_constr);
> +				RETURN(RC_FAIL);
> +			}
> +		} else {
> +			if(last_tag_form !=3D tlv_constr
> +			&& last_tag_form !=3D -1) {
> +				ASN_DEBUG("last_tag_form %d !=3D %d",
> +					last_tag_form, tlv_constr);
> +				RETURN(RC_FAIL);
> +			}
> +		}
> +
> +		/*
> +		 * Fetch and process L from TLV.
> +		 */
> +		len_len =3D ber_fetch_length(tlv_constr,
> +			(const char *)ptr + tag_len, size - tag_len,
> &tlv_len);
> +		ASN_DEBUG("Fetching len =3D %ld", (long)len_len);
> +		switch(len_len) {
> +		case -1: RETURN(RC_FAIL);
> +		case 0: RETURN(RC_WMORE);
> +		}
> +
> +		/*
> +		 * FIXME
> +		 * As of today, the chain of tags
> +		 * must either contain several indefinite length
> TLVs,
> +		 * or several definite length ones.
> +		 * No mixing is allowed.
> +		 */
> +		if(tlv_len =3D=3D -1) {
> +			/*
> +			 * Indefinite length.
> +			 */
> +			if(limit_len =3D=3D -1) {
> +				expect_00_terminators++;
> +			} else {
> +				ASN_DEBUG("Unexpected indefinite
> length "
> +					"in a chain of definite
> lengths");
> +				RETURN(RC_FAIL);
> +			}
> +			ADVANCE(tag_len + len_len);
> +			continue;
> +		} else {
> +			if(expect_00_terminators) {
> +				ASN_DEBUG("Unexpected definite
> length "
> +					"in a chain of indefinite
> lengths");
> +				RETURN(RC_FAIL);
> +			}
> +		}
> +
> +		/*
> +		 * Check that multiple TLVs specify ever decreasing
> length,
> +		 * which is consistent.
> +		 */
> +		if(limit_len =3D=3D -1) {
> +			limit_len    =3D tlv_len + tag_len + len_len;
> +			if(limit_len < 0) {
> +				/* Too great tlv_len value? */
> +				RETURN(RC_FAIL);
> +			}
> +		} else if(limit_len !=3D tlv_len + tag_len + len_len) {
> +			/*
> +			 * Inner TLV specifies length which is
> inconsistent
> +			 * with the outer TLV's length value.
> +			 */
> +			ASN_DEBUG("Outer TLV is %ld and inner is
> %ld",
> +				(long)limit_len, (long)tlv_len);
> +			RETURN(RC_FAIL);
> +		}
> +
> +		ADVANCE(tag_len + len_len);
> +
> +		limit_len -=3D (tag_len + len_len);
> +		if((ssize_t)size > limit_len) {
> +			/*
> +			 * Make sure that we won't consume more bytes
> +			 * from the parent frame than the inferred
> limit.
> +			 */
> +			size =3D limit_len;
> +		}
> +	}
> +
> +	if(opt_tlv_form)
> +		*opt_tlv_form =3D tlv_constr;
> +	if(expect_00_terminators)
> +		*last_length =3D -expect_00_terminators;
> +	else
> +		*last_length =3D tlv_len;
> +
> +	RETURN(RC_OK);
> +}
> diff --git a/libkmod/pkcs7/asn1c-gen/ber_decoder.h
> b/libkmod/pkcs7/asn1c-gen/ber_decoder.h new file mode 100644
> index 000000000000..9fe2e895dfb6
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ber_decoder.h
> @@ -0,0 +1,64 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	_BER_DECODER_H_
> +#define	_BER_DECODER_H_
> +
> +#include <asn_application.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +struct asn_TYPE_descriptor_s;	/* Forward declaration */
> +struct asn_codec_ctx_s;		/* Forward declaration */
> +
> +/*
> + * The BER decoder of any type.
> + * This function may be invoked directly from the application.
> + * The der_encode() function (der_encoder.h) is an opposite to
> ber_decode().
> + */
> +asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx,
> +	struct asn_TYPE_descriptor_s *type_descriptor,
> +	void **struct_ptr,	/* Pointer to a target structure's
> pointer */
> +	const void *buffer,	/* Data to be decoded */
> +	size_t size		/* Size of that buffer */
> +	);
> +
> +/*
> + * Type of generic function which decodes the byte stream into the
> structure.
> + */
> +typedef asn_dec_rval_t (ber_type_decoder_f)(
> +		struct asn_codec_ctx_s *opt_codec_ctx,
> +		struct asn_TYPE_descriptor_s *type_descriptor,
> +		void **struct_ptr, const void *buf_ptr, size_t size,
> +		int tag_mode);
> +
> +/*******************************
> + * INTERNALLY USEFUL FUNCTIONS *
> + *******************************/
> +
> +/*
> + * Check that all tags correspond to the type definition (as given
> in head).
> + * On return, last_length would contain either a non-negative length
> of the
> + * value part of the last TLV, or the negative number of expected
> + * "end of content" sequences. The number may only be negative if the
> + * head->last_tag_form is non-zero.
> + */
> +asn_dec_rval_t ber_check_tags(
> +		struct asn_codec_ctx_s *opt_codec_ctx,	/*
> codec options */
> +		struct asn_TYPE_descriptor_s *type_descriptor,
> +		asn_struct_ctx_t *opt_ctx,	/* saved decoding
> context */
> +		const void *ptr, size_t size,
> +		int tag_mode,		/* {-1,0,1}: IMPLICIT,
> no, EXPLICIT */
> +		int last_tag_form,	/* {-1,0:1}: any,
> primitive, constr */
> +		ber_tlv_len_t *last_length,
> +		int *opt_tlv_form	/* optional tag form */
> +	);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _BER_DECODER_H_ */
> diff --git a/libkmod/pkcs7/asn1c-gen/ber_tlv_length.c
> b/libkmod/pkcs7/asn1c-gen/ber_tlv_length.c new file mode 100644
> index 000000000000..4c2f1e5fd3cc
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ber_tlv_length.c
> @@ -0,0 +1,178 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <ber_tlv_length.h>
> +#include <ber_tlv_tag.h>
> +
> +ssize_t
> +ber_fetch_length(int _is_constructed, const void *bufptr, size_t
> size,
> +		ber_tlv_len_t *len_r) {
> +	const uint8_t *buf =3D (const uint8_t *)bufptr;
> +	unsigned oct;
> +
> +	if(size =3D=3D 0)
> +		return 0;	/* Want more */
> +
> +	oct =3D *(const uint8_t *)buf;
> +	if((oct & 0x80) =3D=3D 0) {
> +		/*
> +		 * Short definite length.
> +		 */
> +		*len_r =3D oct;	/* & 0x7F */
> +		return 1;
> +	} else {
> +		ber_tlv_len_t len;
> +		size_t skipped;
> +
> +		if(_is_constructed && oct =3D=3D 0x80) {
> +			*len_r =3D -1;	/* Indefinite length */
> +			return 1;
> +		}
> +
> +		if(oct =3D=3D 0xff) {
> +			/* Reserved in standard for future use. */
> +			return -1;
> +		}
> +
> +		oct &=3D 0x7F;	/* Leave only the 7 LS bits */
> +		for(len =3D 0, buf++, skipped =3D 1;
> +			oct && (++skipped <=3D size); buf++, oct--) {
> +
> +			len =3D (len << 8) | *buf;
> +			if(len < 0
> +			|| (len >> ((8 * sizeof(len)) - 8) && oct >
> 1)) {
> +				/*
> +				 * Too large length value.
> +				 */
> +				return -1;
> +			}
> +		}
> +
> +		if(oct =3D=3D 0) {
> +			ber_tlv_len_t lenplusepsilon =3D (size_t)len +
> 1024;
> +			/*
> +			 * Here length may be very close or equal to
> 2G.
> +			 * However, the arithmetics used in some
> decoders
> +			 * may add some (small) quantities to the
> length,
> +			 * to check the resulting value against some
> limits.
> +			 * This may result in integer wrap-around,
> which
> +			 * we try to avoid by checking it earlier
> here.
> +			 */
> +			if(lenplusepsilon < 0) {
> +				/* Too large length value */
> +				return -1;
> +			}
> +
> +			*len_r =3D len;
> +			return skipped;
> +		}
> +
> +		return 0;	/* Want more */
> +	}
> +
> +}
> +
> +ssize_t
> +ber_skip_length(asn_codec_ctx_t *opt_codec_ctx,
> +		int _is_constructed, const void *ptr, size_t size) {
> +	ber_tlv_len_t vlen;	/* Length of V in TLV */
> +	ssize_t tl;		/* Length of L in TLV */
> +	ssize_t ll;		/* Length of L in TLV */
> +	size_t skip;
> +
> +	/*
> +	 * Make sure we didn't exceed the maximum stack size.
> +	 */
> +	if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
> +		return -1;
> +
> +	/*
> +	 * Determine the size of L in TLV.
> +	 */
> +	ll =3D ber_fetch_length(_is_constructed, ptr, size, &vlen);
> +	if(ll <=3D 0) return ll;
> +
> +	/*
> +	 * Definite length.
> +	 */
> +	if(vlen >=3D 0) {
> +		skip =3D ll + vlen;
> +		if(skip > size)
> +			return 0;	/* Want more */
> +		return skip;
> +	}
> +
> +	/*
> +	 * Indefinite length!
> +	 */
> +	ASN_DEBUG("Skipping indefinite length");
> +	for(skip =3D ll, ptr =3D ((const char *)ptr) + ll, size -=3D ll;;)
> {
> +		ber_tlv_tag_t tag;
> +
> +		/* Fetch the tag */
> +		tl =3D ber_fetch_tag(ptr, size, &tag);
> +		if(tl <=3D 0) return tl;
> +
> +		ll =3D ber_skip_length(opt_codec_ctx,
> +			BER_TLV_CONSTRUCTED(ptr),
> +			((const char *)ptr) + tl, size - tl);
> +		if(ll <=3D 0) return ll;
> +
> +		skip +=3D tl + ll;
> +
> +		/*
> +		 * This may be the end of the indefinite length
> structure,
> +		 * two consecutive 0 octets.
> +		 * Check if it is true.
> +		 */
> +		if(((const uint8_t *)ptr)[0] =3D=3D 0
> +		&& ((const uint8_t *)ptr)[1] =3D=3D 0)
> +			return skip;
> +
> +		ptr =3D ((const char *)ptr) + tl + ll;
> +		size -=3D tl + ll;
> + 	}
> +
> +	/* UNREACHABLE */
> +}
> +
> +size_t
> +der_tlv_length_serialize(ber_tlv_len_t len, void *bufp, size_t size)
> {
> +	size_t required_size;	/* Size of len encoding */
> +	uint8_t *buf =3D (uint8_t *)bufp;
> +	uint8_t *end;
> +	size_t i;
> +
> +	if(len <=3D 127) {
> +		/* Encoded in 1 octet */
> +		if(size) *buf =3D (uint8_t)len;
> +		return 1;
> +	}
> +
> +	/*
> +	 * Compute the size of the subsequent bytes.
> +	 */
> +	for(required_size =3D 1, i =3D 8; i < 8 * sizeof(len); i +=3D 8) {
> +		if(len >> i)
> +			required_size++;
> +		else
> +			break;
> +	}
> +
> +	if(size <=3D required_size)
> +		return required_size + 1;
> +
> +	*buf++ =3D (uint8_t)(0x80 | required_size);  /* Length of the
> encoding */ +
> +	/*
> +	 * Produce the len encoding, space permitting.
> +	 */
> +	end =3D buf + required_size;
> +	for(i -=3D 8; buf < end; i -=3D 8, buf++)
> +		*buf =3D (uint8_t)(len >> i);
> +
> +	return required_size + 1;
> +}
> +
> diff --git a/libkmod/pkcs7/asn1c-gen/ber_tlv_length.h
> b/libkmod/pkcs7/asn1c-gen/ber_tlv_length.h new file mode 100644
> index 000000000000..349680224401
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ber_tlv_length.h
> @@ -0,0 +1,50 @@
> +/*-
> + * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#ifndef	_BER_TLV_LENGTH_H_
> +#define	_BER_TLV_LENGTH_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef ssize_t ber_tlv_len_t;
> +
> +/*
> + * This function tries to fetch the length of the BER TLV value and
> place it
> + * in *len_r.
> + * RETURN VALUES:
> + *	 0:	More data expected than bufptr contains.
> + *	-1:	Fatal error deciphering length.
> + *	>0:	Number of bytes used from bufptr.
> + * On return with >0, len_r is constrained as -1..MAX, where -1 mean
> + * that the value is of indefinite length.
> + */
> +ssize_t ber_fetch_length(int _is_constructed, const void *bufptr,
> size_t size,
> +	ber_tlv_len_t *len_r);
> +
> +/*
> + * This function expects bufptr to be positioned over L in TLV.
> + * It returns number of bytes occupied by L and V together, suitable
> + * for skipping. The function properly handles indefinite length.
> + * RETURN VALUES:
> + * 	Standard {-1,0,>0} convention.
> + */
> +ssize_t ber_skip_length(
> +	struct asn_codec_ctx_s *opt_codec_ctx,	/* optional
> context */
> +	int _is_constructed, const void *bufptr, size_t size);
> +
> +/*
> + * This function serializes the length (L from TLV) in DER format.
> + * It always returns number of bytes necessary to represent the
> length,
> + * it is a caller's responsibility to check the return value
> + * against the supplied buffer's size.
> + */
> +size_t der_tlv_length_serialize(ber_tlv_len_t len, void *bufptr,
> size_t size); +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif	/* _BER_TLV_LENGTH_H_ */
> diff --git a/libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c
> b/libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c new file mode 100644
> index 000000000000..42708760e089
> --- /dev/null
> +++ b/libkmod/pkcs7/asn1c-gen/ber_tlv_tag.c
> @@ -0,0 +1,144 @@
> +/*-
> + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights
> reserved.
> + * Redistribution and modifications are permitted subject to BSD
> license.
> + */
> +#include <asn_internal.h>
> +#include <ber_tlv_tag.h>
> +#include <errno.h>
> +
> +ssize_t
> +ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) {
> +	ber_tlv_tag_t val;
> +	ber_tlv_tag_t tclass;
> +	size_t skipped;
> +
> +	if(size =3D=3D 0)
> +		return 0;
> +
> +	val =3D *(const uint8_t *)ptr;
> +	tclass =3D (val >> 6);
> +	if((val &=3D 0x1F) !=3D 0x1F) {
> +		/*
> +		 * Simple form: everything encoded in a single octet.
> +		 * Tag Class is encoded using two least significant
> bits.
> +		 */
> +		*tag_r =3D (val << 2) | tclass;
> +		return 1;
> +	}
> +
> +	/*
> +	 * Each octet contains 7 bits of useful information.
> +	 * The MSB is 0 if it is the last octet of the tag.
> +	 */
> +	for(val =3D 0, ptr =3D ((const char *)ptr) + 1, skipped =3D 2;
> +			skipped <=3D size;
> +				ptr =3D ((const char *)ptr) + 1,
> skipped++) {
> +		unsigned int oct =3D *(const uint8_t *)ptr;
> +		if(oct & 0x80) {
> +			val =3D (val << 7) | (oct & 0x7F);
> +			/*
> +			 * Make sure there are at least 9 bits spare
> +			 * at the MS side of a value.
> +			 */
> +			if(val >> ((8 * sizeof(val)) - 9)) {
> +				/*
> +				 * We would not be able to accomodate
> +				 * any more tag bits.
> +				 */
> +				return -1;
> +			}
> +		} else {
> +			val =3D (val << 7) | oct;
> +			*tag_r =3D (val << 2) | tclass;
> +			return skipped;
> +		}
> +	}
> +
> +	return 0;	/* Want more */
> +}
> +
> +
> +ssize_t
> +ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) {
> +	char buf[sizeof("[APPLICATION ]") + 32];
> +	ssize_t ret;
> +
> +	ret =3D ber_tlv_tag_snprint(tag, buf, sizeof(buf));
> +	if(ret >=3D (ssize_t)sizeof(buf) || ret < 2) {
> +		errno =3D EPERM;
> +		return -1;
> +	}
> +
> +	return fwrite(buf, 1, ret, f);
> +}
> +
> +ssize_t
> +ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) {
> +	char *type =3D 0;
> +	int ret;
> +
> +	switch(tag & 0x3) {
> +	case ASN_TAG_CLASS_UNIVERSAL:	type =3D "UNIVERSAL
> ";	break;
> +	case ASN_TAG_CLASS_APPLICATION:	type =3D "APPLICATION
> ";	break;
> +	case ASN_TAG_CLASS_CONTEXT:	type =3D "";
> break;
> +	case ASN_TAG_CLASS_PRIVATE:	type =3D "PRIVATE ";
> break;
> +	}
> +
> +	ret =3D snprintf(buf, size, "[%s%u]", type, ((unsigned)tag) >>
> 2);
> +	if(ret <=3D 0 && size) buf[0] =3D '\0';	/* against broken
> libc's */ +
> +	return ret;
> +}
> +
> +char *
> +ber_tlv_tag_string(ber_tlv_tag_t tag) {
> +	static char buf[sizeof("[APPLICATION ]") + 32];
> +
> +	(void)ber_tlv_tag_snprint(tag, buf, sizeof(buf));
> +
> +	return buf;
> +}
> +
> +
> +size_t
> +ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufp, size_t size) {
> +	int tclass =3D BER_TAG_CLASS(tag);
> +	ber_tlv_tag_t tval =3D BER_TAG_VALUE(tag);
> +	uint8_t *buf =3D (uint8_t *)bufp;
> +	uint8_t *end;
> +	size_t required_size;
> +	size_t i;
> +
> +	if(tval <=3D 30) {
> +		/* Encoded in 1 octet */
> +		if(size) buf[0] =3D (tclass << 6) | tval;
> +		return 1;
> +	} else if(size) {
> +		*buf++ =3D (tclass << 6) | 0x1F;
> +		size--;
> +	}
> +
> +	/*
> +	 * Compute the size of the subsequent bytes.
> +	 */
> +	for(required_size =3D 1, i =3D 7; i < 8 * sizeof(tval); i +=3D 7) {
> +		if(tval >> i)
> +			required_size++;
> +		else
> +			break;
> +	}
> +
> +	if(size < required_size)
> +		return required_size + 1;
> +
> +	/*
> +	 * Fill in the buffer, space permitting.
> +	 */
> +	end =3D buf + required_