Skip to content

Commit

Permalink
pe
Browse files Browse the repository at this point in the history
  • Loading branch information
5HT committed Nov 1, 2024
1 parent 4a3d430 commit 90c8379
Show file tree
Hide file tree
Showing 6 changed files with 529 additions and 48 deletions.
53 changes: 43 additions & 10 deletions lib/encryption/cms.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule CA.CMS do
def oid(:"id-cms-encryptedData"), do: {1,2,840,113549,1,7,5}

def contentInfo(cms) do {:ok, ci} = :"CryptographicMessageSyntax-2010".decode :ContentInfo, cms ; ci end
def contentInfoFile(file) do {:ok, bin} = :file.read_file file ; contentInfo(bin) end

def map(:'dhSinglePass-stdDH-sha512kdf-scheme'), do: {:kdf, :sha512}
def map(:'dhSinglePass-stdDH-sha384kdf-scheme'), do: {:kdf, :sha384}
Expand Down Expand Up @@ -148,12 +149,21 @@ defmodule CA.CMS do

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

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

Check warning on line 156 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)
[
resourceType: :RecipientInfo,
issuer: CA.CRT.rdn(issuer),
keyAlg: :erlang.element(1,CA.ALG.lookup(keyAlg)),
]
end

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

Check warning on line 165 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 {:Attribute,code,[{:asn1_OPENTYPE,b}],_} ->
signedAttributes = :lists.map(fn {_,code,[{:asn1_OPENTYPE,b}],_} ->
CA.CRT.oid(code, b)
end, signedAttrs)
attributes = case attrs do
Expand All @@ -170,22 +180,45 @@ defmodule CA.CMS do
]
end

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

def parseSignData(bin) do
{_, {:ContentInfo, oid, ci}} = :KEP.decode(:ContentInfo, bin)
{:ok, {:SignedData, ver, alg, x, c, x1, sis}} = :KEP.decode(:SignedData, ci)
def parseData(content) do
{:ok, {:SignedData, ver, alg, x, c, x1, sis}} = :KEP.decode(:SignedData, content)

Check warning on line 184 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 184 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 185 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({alg,oid,x,c,x1,sis}),
cert: parseSignDataCert(c,sis),
signerInfo: parseSignerInfos(sis),
signedContent: data,
]
end

def parseSignDataCert({_,_,_,:asn1_NOVALUE,_,_}), do: []
def parseSignDataCert({_,_,_,certs,_,si}), do: :lists.map(fn cert -> CA.CRT.parseCert(cert, si) end, certs)
def parseEnvelopedData(content) do
{:ok, {:EnvelopedData, oid, {_,ri}, ci}} = :KEP.decode(:EnvelopedData, content)
{:EncryptedContentInfo, _, {_,encOID,<<_::16,iv::binary>>},data} = ci
[
resourceType: :EnvelopedData,
ver: CA.ALG.oid(oid),
signerInfo: parseRecipientInfos(ri),
encryption: CA.ALG.oid(encOID),
encryptedContentInfo: [iv: :base64.encode(iv), data: :base64.encode(data)]
]
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 parseContentInfoFile(file) do {:ok, bin} = :file.read_file file ; parseContentInfo(bin) end
def parseContentInfo(bin) do
{:ok, {:ContentInfo, oid, content}} = :KEP.decode(:ContentInfo, bin)
case CA.AT.oid(oid) do
:data -> parseData(content)
:signedData -> parseData(content)
:envelopedData -> parseEnvelopedData(content)
_ -> []
end
end

def parseSignDataCert(:asn1_NOVALUE,_), do: []
def parseSignDataCert(certs,si), do: :lists.map(fn cert -> CA.CRT.parseCert(cert, si) end, certs)

end
9 changes: 9 additions & 0 deletions lib/oid/at.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ defmodule CA.AT do
{:"id-at-rsaEncryption", {1, 2, 840, 113549, 1, 1, 1}},
{:"id-at-sha1WithRSAEncryption", {1, 2, 840, 113549, 1, 1, 5}},
{:"id-at-sha512-256WithRSAEncryption", {1, 2, 840, 113549, 1, 1, 16}},
{:"PKCS-7", {1, 2, 840, 113549, 1, 7}},
{:data, {1, 2, 840, 113549, 1, 7, 1}},
{:signedData, {1, 2, 840, 113549, 1, 7, 2}},
{:envelopedData, {1, 2, 840, 113549, 1, 7, 3}},
{:signedAndEnvelopedData, {1, 2, 840, 113549, 1, 7, 4}},
{:digestedData, {1, 2, 840, 113549, 1, 7, 5}},
{:encryptedData, {1, 2, 840, 113549, 1, 7, 6}},
{:dataWithAttributes, {1, 2, 840, 113549, 1, 7, 7}},
{:encryptedPrivateKeyInfo, {1, 2, 840, 113549, 1, 7, 8}},
{:"id-at-dhKeyAgreement", {1, 2, 840, 113549, 1, 3, 1}},
{:"id-at-emailAddress", {1, 2, 840, 113549, 1, 9, 1}},
{:"id-at-unstructuredName", {1, 2, 840, 113549, 1, 9, 2}},
Expand Down
4 changes: 4 additions & 0 deletions lib/oid/pe.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
defmodule CA.PE do
@moduledoc "CA Private Extensions OIDs."
def oid(:"id-pe-authorityInfoAccess"), do: {1, 3, 6, 1, 5, 5, 7, 1, 1}
end
72 changes: 34 additions & 38 deletions lib/services/crt.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ defmodule CA.CRT do

def readSignature(name \\ "2.p7s") do
{:ok, bin} = :file.read_file name
ber = CA.CMS.parseSignData(bin)
ber = CA.CMS.parseData(bin)
ber
end

Expand Down Expand Up @@ -51,46 +51,40 @@ defmodule CA.CRT do
:erlang.tuple_to_list(x)),'.')) end, list)
end

def oid({1,3,6,1,5,5,7,1,1}, v), do: {:authorityInfoAccess, pair(v,[])}
def oid({1,3,6,1,4,1,11129,2,4,2}, v), do: {:signedCertificateTimestamp, :base64.encode(hd(pair(v,[])))}
def oid({1,3,6,1,5,5,7,1,11},v), do: {:subjectInfoAccess, pair(v,[])}
def oid({1,3,6,1,5,5,7,1,3}, v), do: {:qcStatements, mapOidsDecode(v)}
def oid({2,5,29,9},v), do: {:subjectDirectoryAttributes, pair(v,[])}
def oid({2,5,29,14},v), do: {:subjectKeyIdentifier, :base64.encode(hd(pair(v,[])))}
def oid({2,5,29,15},[v]), do: {:keyUsage, CA.EST.decodeKeyUsage(<<3,2,v::binary>>) }
def oid({2,5,29,16},v), do: {:privateKeyUsagePeriod, v}
def oid({2,5,29,17},v), do: {:subjectAltName, :lists.map(fn x ->
case CA.ALG.lookup(:oid.decode(x)) do
false -> x
{alg,_} -> alg
end end, v)}
def oid({2,5,29,37},v), do: {:extKeyUsage, mapOids(:lists.map(fn x -> :oid.decode(x) end, v)) }
def oid({2,5,29,19},v), do: {:basicConstraints, v}
def oid({2,5,29,31},v), do: {:cRLDistributionPoints, pair(v,[])}
def oid({2,5,29,32},v), do: {:certificatePolicies, mapOids(:lists.map(fn x -> :oid.decode(x) end, v))}
def oid({2,5,29,35},v), do: {:authorityKeyIdentifier, :base64.encode(hd(pair(v,[])))}
def oid({2,5,29,46},v), do: {:freshestCRL, pair(v,[])}
def oid({2,5,29,97},v), do: {:unknown97, v}
def oid({1,2,840,113549,1,9,3},v), do: {:contentType, hd(mapOidsDecode([v]))}
def oid({1,2,840,113549,1,9,4},v), do: {:messageDigest, :base64.encode(:erlang.element(2,:KEP.decode(:MessageDigest, v)))}
def oid({1,2,840,113549,1,9,5},v), do: {:signingTime, :erlang.element(2,:erlang.element(1,:asn1rt_nif.decode_ber_tlv(v)))}

def oid({1, 2, 840, 113549, 1, 9, 16, 2}, v) do {:"id-aa", v} end
def oid({1, 2, 840, 113549, 1, 9, 16, 2, 14}, v) do {:"id-aa-timeStampToken", v}
def oid({1,3,6,1,5,5,7,1,1}, v), do: {:authorityInfoAccess, pair(v,[])}
def oid({1,3,6,1,4,1,11129,2,4,2}, v), do: {:signedCertificateTimestamp, :base64.encode(hd(pair(v,[])))}
def oid({1,3,6,1,5,5,7,1,11},v), do: {:subjectInfoAccess, pair(v,[])}
def oid({1,3,6,1,5,5,7,1,3}, v), do: {:qcStatements, mapOidsDecode(v)}
def oid({2,5,29,9},v), do: {:subjectDirectoryAttributes, pair(v,[])}
def oid({2,5,29,14},v), do: {:subjectKeyIdentifier, :base64.encode(hd(pair(v,[])))}
def oid({2,5,29,15},[v]), do: {:keyUsage, CA.EST.decodeKeyUsage(<<3,2,v::binary>>) }
def oid({2,5,29,16},v), do: {:privateKeyUsagePeriod, v}
def oid({2,5,29,17},v), do: {:subjectAltName, :lists.map(fn x -> case CA.ALG.lookup(:oid.decode(x)) do false -> x ; {alg,_} -> alg end end, v)}
def oid({2,5,29,37},v), do: {:extKeyUsage, mapOids(:lists.map(fn x -> :oid.decode(x) end, v)) }
def oid({2,5,29,19},v), do: {:basicConstraints, v}
def oid({2,5,29,31},v), do: {:cRLDistributionPoints, pair(v,[])}
def oid({2,5,29,32},v), do: {:certificatePolicies, mapOids(:lists.map(fn x -> :oid.decode(x) end, v))}
def oid({2,5,29,35},v), do: {:authorityKeyIdentifier, :base64.encode(hd(pair(v,[])))}
def oid({2,5,29,46},v), do: {:freshestCRL, pair(v,[])}
def oid({1,2,840,113549,1,9,3},v), do: {:contentType, CA.AT.oid(CA.EST.decodeObjectIdentifier(v)) }
def oid({1,2,840,113549,1,9,4},v), do: {:messageDigest, :base64.encode(:erlang.element(2,:KEP.decode(:MessageDigest, v)))}
def oid({1,2,840,113549,1,9,5},v), do: {:signingTime, :erlang.element(2,:erlang.element(1,:asn1rt_nif.decode_ber_tlv(v)))}
def oid({1,2,840,113549,1,9,16,2},v), do: {:"id-aa", v}
def oid({1,2,840,113549,1,9,16,2,14},v) do
{:ok, {:ContentInfo, oid, value}} = :KEP.decode(:ContentInfo,v)
{:ok, {:SignedData, _, _alg, {_,_,x}, _c, _x1, _si}} = :KEP.decode(:SignedData, value)
{:ok, {:TSTInfo, _vsn, _oid, {:MessageImprint, _, x}, serial, ts, _,_,_,_}} = :KEP.decode(:TSTInfo, x)
{:timeStampToken, {hd(mapOids([oid])), serial, :erlang.iolist_to_binary(ts), :base64.encode(x)}}
end
def oid({1, 2, 840, 113549, 1, 9, 16, 2, 18}, v) do {:"id-aa-ets-signerAttr", v} end
def oid({1, 2, 840, 113549, 1, 9, 16, 2, 19}, v) do {:"id-aa-ets-otherSigCert", v} end
def oid({1, 2, 840, 113549, 1, 9, 16, 2, 20}, v) do
def oid({1,2,840,113549,1,9,16,2,18},v) do {:"id-aa-ets-signerAttr", v} end
def oid({1,2,840,113549,1,9,16,2,19},v) do {:"id-aa-ets-otherSigCert", v} end
def oid({1,2,840,113549,1,9,16,2,20},v) do
{:ok, {:ContentInfo, oid, value}} = :KEP.decode(:ContentInfo,v)
{:ok, {:SignedData, _, _alg, {_,_,x}, _c, _x1, _si}} = :KEP.decode(:SignedData, value)
{:ok, {:TSTInfo, _vsn, _oid, {:MessageImprint, _, x}, serial, ts, _,_,_,_}} = :KEP.decode(:TSTInfo, x)
{:contentTimestamp, {hd(mapOids([oid])), serial, :erlang.iolist_to_binary(ts), :base64.encode(x)}}
end
def oid({1, 2, 840, 113549, 1, 9, 16, 2, 22}, v) do
def oid({1,2,840,113549,1,9,16,2,22},v) do
{:ok, x} = :KEP.decode(:CompleteRevocationRefs, v)
{:revocationRefs, x}
end
Expand Down Expand Up @@ -123,14 +117,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, 4}), do: "sn" # sureName
def rdn({2, 5, 4, 3}), do: "commonName" # commonName
def rdn({2, 5, 4, 4}), do: "surename" # sn
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({0,9,2342,19200300,100,1,25}), do: "dc"
def rdn({2, 5, 4, 10}), do: "o" # organization
def rdn({2, 5, 4, 11}), do: "ou" # organizationalUnit
def rdn({2, 5, 4, 6}), do: "country" # c
def rdn({2, 5, 4, 7}), do: "localityName" # l
def rdn({2, 5, 4, 8}), do: "stateOrProvinceName"
def rdn({0,9,2342,19200300,100,1,25}), do: "domainComponen" # dc
def rdn({2, 5, 4, 10}), do: "organization" # o
def rdn({2, 5, 4, 11}), do: "organizationalUnit" # ou
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 @@ -149,6 +144,7 @@ defmodule CA.CRT do
{_,oid,{_,list}} -> {rdn(oid),"#{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}"
Expand Down
26 changes: 26 additions & 0 deletions priv/csr/KEP.asn1
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,32 @@ SignedData ::= SEQUENCE {
crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
signerInfos SignerInfos }

EnvelopedData ::= SEQUENCE {
version INTEGER,
recipientInfos RecipientInfos,
encryptedContentInfo EncryptedContentInfo
}

RecipientInfos ::= CHOICE { riSet SET OF RecipientInfo, riSequence SEQUENCE OF RecipientInfo }
EncryptedContentInfo ::= SEQUENCE {
contentType ContentType,
contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
}

ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
EncryptedContent ::= OCTET STRING

RecipientInfo ::= SEQUENCE {
version INTEGER {riVer0(0)} (riVer0),
issuerAndSerialNumber IssuerAndSerialNumber,
keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
encryptedKey EncryptedKey
}

EncryptedKey ::= OCTET STRING

EncapsulatedContentInfo ::= SEQUENCE {
eContentType ContentType,
eContent [0] EXPLICIT OCTET STRING OPTIONAL }
Expand Down
Loading

0 comments on commit 90c8379

Please sign in to comment.