Skip to content

Commit

Permalink
CMS is unified across KEP and CMS-2009, CMS-2010.
Browse files Browse the repository at this point in the history
  • Loading branch information
5HT committed Nov 1, 2024
1 parent 8c8e9ba commit 87c253f
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 103 deletions.
128 changes: 100 additions & 28 deletions include/KEP.hrl
Original file line number Diff line number Diff line change
@@ -1,38 +1,46 @@
%% Generated by the Erlang ASN.1 compiler. Version: 5.2.2
%% Generated by the Erlang ASN.1 compiler. Version: 5.0.17
%% Purpose: Erlang record definitions for each named and unnamed
%% SEQUENCE and SET, and macro definitions for each value
%% definition in module KEP.

-ifndef(_KEP_HRL_).
-define(_KEP_HRL_, true).

-record('ContentInfo', {
contentType,
content
-record('AttributeTypeAndValue', {
type,
value
}).

-record('CrlValidatedID', {
crlHash,
crlIdentifier = asn1_NOVALUE
-record('AlgorithmIdentifier', {
algorithm,
parameters = asn1_NOVALUE
}).

-record('OcspListID', {
ocspResponses
-record('CertificateList', {
tbsCertList,
signatureAlgorithm,
signatureValue = asn1_NOVALUE
}).

-record('OcspResponsesID', {
ocspIdentifier,
ocspRepHash = asn1_NOVALUE
-record('TBSCertList', {
version = asn1_NOVALUE,
signature,
issuer,
thisUpdate = asn1_NOVALUE,
nextUpdate = asn1_NOVALUE,
revokedCertificates = asn1_NOVALUE,
crlExtensions = asn1_NOVALUE
}).

-record('OtherRevRefs', {
otherRevRefType,
otherRevRefs
-record('TBSCertList_revokedCertificates_SEQOF', {
userCertificate,
revocationDate,
crlEntryExtensions = asn1_NOVALUE
}).

-record('OcspIdentifier', {
ocspResponderID,
producedAt
-record('ContentInfo', {
contentType,
content
}).

-record('SignedData', {
Expand All @@ -44,6 +52,25 @@
signerInfos
}).

-record('EnvelopedData', {
version,
recipientInfos,
encryptedContentInfo
}).

-record('EncryptedContentInfo', {
contentType,
contentEncryptionAlgorithm,
encryptedContent = asn1_NOVALUE
}).

-record('RecipientInfoUA', {
version,
issuerAndSerialNumber,
keyEncryptionAlgorithm,
encryptedKey
}).

-record('EncapsulatedContentInfo', {
eContentType,
eContent = asn1_NOVALUE
Expand Down Expand Up @@ -112,6 +139,54 @@
crlNumber = asn1_NOVALUE
}).

-record('CrlValidatedID', {
crlHash,
crlIdentifier = asn1_NOVALUE
}).

-record('OcspListID', {
ocspResponses
}).

-record('OcspResponsesID', {
ocspIdentifier,
ocspRepHash = asn1_NOVALUE
}).

-record('OtherRevRefs', {
otherRevRefType,
otherRevRefs
}).

-record('OcspIdentifier', {
ocspResponderID,
producedAt
}).

-record('RevocationValues', {
crlVals = asn1_NOVALUE,
ocspVals = asn1_NOVALUE,
otherRevVals = asn1_NOVALUE
}).

-record('OtherSigningCertificate', {
certs,
policies = asn1_NOVALUE
}).

-record('OtherCertID', {
otherCertHash,
issuerSerial = asn1_NOVALUE
}).

-record('OtherRevVals', {
otherRevValType
}).

-record('CRLListID', {
crls
}).

-record('BasicOCSPResponse', {
tbsResponseData,
signatureAlgorithm,
Expand Down Expand Up @@ -147,18 +222,15 @@
singleExtensions = asn1_NOVALUE
}).

-record('RevocationValues', {
crlVals = asn1_NOVALUE,
ocspVals = asn1_NOVALUE,
otherRevVals = asn1_NOVALUE
-record('QCStatement', {
statementId,
statementInfo = asn1_NOVALUE
}).

-record('OtherRevVals', {
otherRevValType
}).

-record('CRLListID', {
crls
-record('MonetaryValue', {
currency,
amount,
exponent
}).

-record('MessageImprint', {
Expand Down
85 changes: 70 additions & 15 deletions lib/encryption/cms.ex
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,15 @@ defmodule CA.CMS do
CA.AES.decrypt(:'id-aes256-CBC', data, unwrap, iv)
end

# ASN.1 DER Parsing Facilities

def parseSignDataFile(file) do
{_, bin} = :file.read_file file
parseData(bin)
end

def parseRecipientInfo([]) do [] end
def parseRecipientInfo({scheme,ri}) do {scheme,ri} end
def parseRecipientInfo(ri) do
{:RecipientInfo, _, {_,issuer,_}, {_,keyAlg,_}, data} = ri

Check warning on line 160 in lib/encryption/cms.ex

View workflow job for this annotation

GitHub Actions / build

variable "data" is unused (if the variable is not meant to be used, prefix it with an underscore)
[
Expand All @@ -163,12 +167,16 @@ defmodule CA.CMS do

def parseSignerInfo(si) do
{:SignerInfo, :v1, {_,{_,issuer,_}}, {_,keyAlg,_}, signedAttrs, {_,signatureAlg,_}, sign, attrs} = si

Check warning on line 169 in lib/encryption/cms.ex

View workflow job for this annotation

GitHub Actions / build

variable "sign" is unused (if the variable is not meant to be used, prefix it with an underscore)
signedAttributes = :lists.map(fn {_,code,[{:asn1_OPENTYPE,b}],_} ->
CA.CRT.oid(code, b)
end, signedAttrs)
signedAttributes = :lists.map(fn {_,code,[{:asn1_OPENTYPE,b}]} -> CA.CRT.oid(code, b)
{_,code,[{:asn1_OPENTYPE,b}],_} -> CA.CRT.oid(code, b)
{_,code,b} -> {CA.AT.oid(code), b}
end, signedAttrs)
attributes = case attrs do
:asn1_NOVALUE -> []
_ -> :lists.map(fn {_,code,[{:asn1_OPENTYPE,b}],_} -> CA.CRT.oid(code, b) end, attrs)
_ -> :lists.map(fn {_,code,[{:asn1_OPENTYPE,b}]} -> CA.CRT.oid(code, b)
{_,code,[{:asn1_OPENTYPE,b}],_} -> CA.CRT.oid(code, b)
{_,code,b} -> {CA.AT.oid(code), b}
end, attrs)
end
[
resourceType: :SignerInfo,
Expand All @@ -180,21 +188,37 @@ defmodule CA.CMS do
]
end

def parseData(content) do
{:ok, {:SignedData, ver, alg, x, c, x1, sis}} = :KEP.decode(:SignedData, content)
def parseDataBin(content) do
{:ok, envelopedData} = :KEP.decode(:SignedData, content)
parseData(envelopedData)
end
def parseData({:SignedData, ver, alg, x, c, x1, sis}) do

Check warning on line 195 in lib/encryption/cms.ex

View workflow job for this annotation

GitHub Actions / build

variable "alg" is unused (if the variable is not meant to be used, prefix it with an underscore)

Check warning on line 195 in lib/encryption/cms.ex

View workflow job for this annotation

GitHub Actions / build

variable "x1" is unused (if the variable is not meant to be used, prefix it with an underscore)
{:EncapsulatedContentInfo, contentOid, data} = x

Check warning on line 196 in lib/encryption/cms.ex

View workflow job for this annotation

GitHub Actions / build

variable "contentOid" is unused (if the variable is not meant to be used, prefix it with an underscore)
[
resourceType: :SignedData,
version: ver,
cert: parseSignDataCert(c,sis),
cert: parseSignDataCert(case c do {:certificate,cert} -> cert ; c -> c end,sis),
signerInfo: parseSignerInfos(sis),
signedContent: data,
]
end

def parseEnvelopedData(content) do
{:ok, {:EnvelopedData, oid, {_,ri}, ci}} = :KEP.decode(:EnvelopedData, content)
{:EncryptedContentInfo, _, {_,encOID,<<_::16,iv::binary>>},data} = ci
def parseEnvelopedDataBin(content) do
{:ok, envelopedData} = :KEP.decode(:EnvelopedData, content)
parseEnvelopedData(envelopedData)
end

def parseEnvelopedData({:EnvelopedData, _, oid, list, ci, tag}) do

Check warning on line 211 in lib/encryption/cms.ex

View workflow job for this annotation

GitHub Actions / build

variable "tag" is unused (if the variable is not meant to be used, prefix it with an underscore)
parseEnvelopedData({:EnvelopedData, oid, list, ci}) end

def parseEnvelopedData({:EnvelopedData, oid, {:riSet, ri}, ci}) do
parseEnvelopedData({:EnvelopedData, oid, ri, ci}) end

def parseEnvelopedData({:EnvelopedData, oid, ri, ci}) do
{:EncryptedContentInfo, oid2, {_,encOID,<<_::16,iv::binary>>},data} = case ci do

Check warning on line 218 in lib/encryption/cms.ex

View workflow job for this annotation

GitHub Actions / build

variable "oid2" is unused (if the variable is not meant to be used, prefix it with an underscore)
{:EncryptedContentInfo, x, {y,encOID,{_,bin}},data} -> {:EncryptedContentInfo, x, {y,encOID,bin},data}
{:EncryptedContentInfo, x, {y,encOID,bin},data} -> {:EncryptedContentInfo, x, {y,encOID,bin},data}
end
[
resourceType: :EnvelopedData,
ver: CA.ALG.oid(oid),
Expand All @@ -204,19 +228,50 @@ defmodule CA.CMS do
]
end

def parseSignerInfos(sis) do :lists.map(fn si -> CA.CMS.parseSignerInfo(si) end, sis) end
def parseRecipientInfos(sis) do :lists.map(fn si -> CA.CMS.parseRecipientInfo(si) end, sis) end
def parseSignerInfos(sis) do :lists.map(fn si -> CA.CMS.parseSignerInfo(si) end, sis) end
def parseRecipientInfos(sis) do :lists.map(fn si -> CA.CMS.parseRecipientInfo(si) end, sis) end

def testECC() do

Check warning on line 234 in lib/encryption/cms.ex

View workflow job for this annotation

GitHub Actions / build

clauses with the same name and arity (number of arguments) should be grouped together, "def testECC/0" was previously defined (lib/encryption/cms.ex:119)
{:ok,base} = :file.read_file "priv/certs/encrypted.txt"
[_,s] = :string.split base, "\n\n"
x = :base64.decode s
:'CryptographicMessageSyntax-2010'.decode(:ContentInfo, x)
end

def parseContentInfoSMIME(file) do
{:ok, smime} = :file.read_file(file)
[_,base] = :string.split(smime, "\n\n")
parseContentInfoBin(:base64.decode(base))
end
def parseContentInfoB64(file) do {:ok, bin} = :file.read_file file ; parseContentInfoBin(:base64.decode(bin)) end
def parseContentInfoFile(file) do {:ok, bin} = :file.read_file file ; parseContentInfoBin(bin) end
def parseContentInfoBinUA(bin) do {:ok, contentInfo} = :KEP.decode(:ContentInfo, bin) ; parseContentInfo(contentInfo, true) end
def parseContentInfoBinX509(bin) do {:ok, contentInfo} = :'CryptographicMessageSyntax-2010'.decode(:ContentInfo, bin) ; parseContentInfo(contentInfo, false) end

def parseContentInfoBin(bin) do
case :application.get_env(:ca, :ukrainian, :parseContentInfoBinUA) do
:parseContentInfoBinX509 -> CA.CMS.parseContentInfoBinX509(bin)
:parseContentInfoBinUA -> CA.CMS.parseContentInfoBinUA(bin)
_ -> CA.CMS.parseContentInfoBinUA(bin)
end
end

def parseContentInfoFile(file) do {:ok, bin} = :file.read_file file ; parseContentInfo(bin) end
def parseContentInfo(bin) do
{:ok, {:ContentInfo, oid, content}} = :KEP.decode(:ContentInfo, bin)
def parseContentInfo({:ContentInfo, oid, content}, false) do
case CA.AT.oid(oid) do
:data -> parseData(content)
:signedData -> parseData(content)
:envelopedData -> parseEnvelopedData(content)
_ -> []
end
end
def parseContentInfo({:ContentInfo, oid, content}, true) do
case CA.AT.oid(oid) do
:data -> parseDataBin(content)
:signedData -> parseDataBin(content)
:envelopedData -> parseEnvelopedDataBin(content)
_ -> []
end
end

def parseSignDataCert(:asn1_NOVALUE,_), do: []
def parseSignDataCert(certs,si), do: :lists.map(fn cert -> CA.CRT.parseCert(cert, si) end, certs)
Expand Down
38 changes: 23 additions & 15 deletions lib/services/crt.ex
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,15 @@ defmodule CA.CRT do
def flat(code,k,acc) when is_list(k), do: [:lists.map(fn x -> flat(code,x,acc) end, k)|acc]
def flat(_code,k,acc) when is_binary(k), do: [k|acc]

def rdn({2, 5, 4, 3}), do: "cn" # "commonName"
def rdn({2, 5, 4, 3}), do: "cn" # "commonName"
def rdn({2, 5, 4, 4}), do: "sn" # "surename"
def rdn({2, 5, 4, 5}), do: "serialNumber"
def rdn({2, 5, 4, 6}), do: "c" # "country"
def rdn({2, 5, 4, 7}), do: "l" # "localityName"
def rdn({2, 5, 4, 8}), do: "stateOrProvinceName"
def rdn({0,9,2342,19200300,100,1,25}), do: "dc" # "domainComponen"
def rdn({2, 5, 4, 10}), do: "o" # "organization"
def rdn({2, 5, 4, 10}), do: "o" # "organization"
def rdn({2, 5, 4, 11}), do: "ou" # "organizationalUnit"

def rdn({2, 5, 4, 5}), do: "serialNumber"
def rdn({2, 5, 4, 8}), do: "stateOrProvinceName"
def rdn({2, 5, 4, 12}), do: "title"
def rdn({2, 5, 4, 13}), do: "description"
def rdn({2, 5, 4, 14}), do: "device"
Expand All @@ -137,17 +137,20 @@ defmodule CA.CRT do
def rdn({2, 5, 6, 7}), do: "organizationalPerson"
def rdn({2, 5, 6, 8}), do: "organizationalRole"
def rdn({2, 5, 6, 9}), do: "groupOfNames"

def rdn({0,9,2342,19200300,100,1,25}), do: "dc" # "domainComponent"
def rdn({:rdnSequence, list}) do
:lists.map(fn [{_,oid,{_,list}}] -> {rdn(oid),"#{list}"}
[{_,oid,list}] -> {rdn(oid),"#{list}"}
{_,oid,{_,list}} -> {rdn(oid),"#{list}"}
{_,oid,list} -> {rdn(oid),"#{list}"} end, list)
{_,oid, list} -> {rdn(oid),"#{list}"} end, list)
end
def rdn(x), do: "#{x}"

def rdn2({:rdnSequence, list}) do
Enum.join :lists.map(fn [{_,oid,{_,list}}] -> "#{rdn(oid)}=#{list}"
{_,oid,{_,list}} -> "#{rdn(oid)}=#{list}"
{_,oid,list} -> "#{rdn(oid)}=#{list}" end, list), "/"
{_,oid,{_,list}} -> "#{rdn(oid)}=#{list}"
{_,oid, list} -> "#{rdn(oid)}=#{list}" end, list), "/"
end

def decodePointFromPublic(oid0,oid,publicKey) do
Expand All @@ -165,14 +168,24 @@ defmodule CA.CRT do

def decodePublicKey(oid,oid2,publicKey) do
case oid do
{1,2,804,2,1,1,1,1,3,1,1} -> :base64.encode publicKey
{1,2,804,2,1,1,1,1,3,1,1} -> :base64.encode publicKey
_ -> decodePointFromPublic(oid, CA.EST.decodeObjectIdentifier(oid2),publicKey)
end
end

def parseCertPEM(file) do {:ok, bin} = :file.read_file file ; list = :public_key.pem_decode(bin) ; :lists.map(fn x -> parseCert(:public_key.pem_entry_decode(x)) end, list) end
def parseCertB64(file) do {:ok, bin} = :file.read_file file ; parseCertBin(:base64.decode(bin)) end
def parseCertFile(file) do {:ok, bin} = :file.read_file file ; parseCertBin(bin) end
def parseCertBin(bin) do {:ok, cert} = :"AuthenticationFramework".decode(:Certificate, bin) ; parseCert(cert) end

def parseCert(cert, _) do parseCert(cert) end
def parseCert({:certificate, cert}) do parseCert(cert) end
def parseCert(cert) do
{:Certificate, tbs, _, _} = cert
{:Certificate, tbs, _, _} = case cert do
{:Certificate, tbs, x, y} -> {:Certificate, tbs, x, y}
{:Certificate, tbs, x, y, _} -> {:Certificate, tbs, x, y}
end

{_, ver, serial, {_,alg,_}, issuer, {_,{_,nb},{_,na}}, issuee,
{:SubjectPublicKeyInfo, {_, oid, oid2}, publicKey}, _b, _c, exts} = tbs
extensions = :lists.map(fn {:Extension,code,_x,b} ->
Expand All @@ -190,10 +203,5 @@ defmodule CA.CRT do
]
end

def parseCertFile(file) do
{:ok, bin} = :file.read_file file
{:ok, cert} = :"AuthenticationFramework".decode :Certificate, bin
parseCert(cert)
end

end
Loading

0 comments on commit 87c253f

Please sign in to comment.