Skip to content

Commit

Permalink
cleanup AES ciphers
Browse files Browse the repository at this point in the history
  • Loading branch information
5HT committed Jul 31, 2023
1 parent 93bc63a commit 9e9de12
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 56 deletions.
139 changes: 103 additions & 36 deletions lib/aes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,97 @@ defmodule CA.AES do
def readPEM(folder, name), do: hd(:public_key.pem_decode(e(2, :file.read_file(folder <> name))))
def shared(pub, key, scheme), do: :crypto.compute_key(:ecdh, pub, key, scheme)

def decryptAES256ECB(data, key, iv \\ :crypto.strong_rand_bytes(16)) do
:crypto.crypto_one_time(:aes_256_ecb,key,iv,data,[{:encrypt,false}])
def decryptAES128GCM(data, key, _iv) do
<<iv::binary-16, tag::binary-16, bin::binary>> = data
:crypto.crypto_one_time_aead(:aes_128_gcm, key, iv, bin, "AES256GCM", tag, false)
end

def decryptAES256CBC(data, key, iv \\ :crypto.strong_rand_bytes(16)) do
:crypto.crypto_one_time(:aes_256_cbc,key,iv,data,[{:encrypt,false}])
def decryptAES128CCM(data, key, _iv) do
<<iv::binary-16, tag::binary-16, bin::binary>> = data
:crypto.crypto_one_time_aead(:aes_128_ccm, key, iv, bin, "AES256GCM", tag, false)
end

def decryptAES256GCM(data, key, iv \\ :crypto.strong_rand_bytes(16)) do
def decryptAES256GCM(data, key, _iv) do
<<iv::binary-16, tag::binary-16, bin::binary>> = data
:crypto.crypto_one_time_aead(:aes_256_gcm, key, iv, data, "AES256GCM", tag, false)
:crypto.crypto_one_time_aead(:aes_256_gcm, key, iv, bin, "AES256GCM", tag, false)
end

def decryptAES256CCM(data, key, iv \\ :crypto.strong_rand_bytes(16)) do
def decryptAES256CCM(data, key, _iv) do
<<iv::binary-16, tag::binary-16, bin::binary>> = data
:crypto.crypto_one_time_aead(:aes_256_ccm, key, iv, data, "AES256CCM", tag, false)
:crypto.crypto_one_time_aead(:aes_256_ccm, key, iv, bin, "AES256GCM", tag, false)
end

def decryptAES256CBC(data, key, iv) do
:crypto.crypto_one_time(:aes_256_cbc,key,iv,data,[{:encrypt,false},{:padding,:pkcs_padding}])
end

def decryptAES128CBC(data, key, iv) do
:crypto.crypto_one_time(:aes_128_cbc,key,iv,data,[{:encrypt,false},{:padding,:pkcs_padding}])
end

def decryptAES256ECB(data, key, _iv) do
:crypto.crypto_one_time(:aes_256_ecb,key,data,[{:encrypt,false},{:padding,:pkcs_padding}])
end

def decryptAES128ECB(data, key, _iv) do
:crypto.crypto_one_time(:aes_128_ecb,key,data,[{:encrypt,false},{:padding,:pkcs_padding}])
end

def encryptAES256ECB(data, key, _iv) do
:crypto.crypto_one_time(:aes_256_ecb,key,data,[{:encrypt,true},{:padding,:pkcs_padding}])
end

def encryptAES256ECB(data, key, iv \\ :crypto.strong_rand_bytes(16)) do
:crypto.crypto_one_time(:aes_256_ecb,key,iv,data,[{:encrypt,true}])
def encryptAES128ECB(data, key, _iv) do
:crypto.crypto_one_time(:aes_128_ecb,key,data,[{:encrypt,true},{:padding,:pkcs_padding}])
end

def encryptAES256CBC(data, key, iv \\ :crypto.strong_rand_bytes(16)) do
:crypto.crypto_one_time(:aes_256_cbc,key,iv,data,[{:encrypt,true}])
def encryptAES256CBC(data, key, iv) do
:crypto.crypto_one_time(:aes_256_cbc,key,iv,data,[{:encrypt,true},{:padding,:pkcs_padding}])
end

def encryptAES256GCM(data, key, iv \\ :crypto.strong_rand_bytes(16)) do
def encryptAES128CBC(data, key, iv) do
:crypto.crypto_one_time(:aes_128_cbc,key,iv,data,[{:encrypt,true},{:padding,:pkcs_padding}])
end

def encryptAES256GCM(data, key, iv) do
{cipher, tag} = :crypto.crypto_one_time_aead(:aes_256_gcm, key, iv, data, "AES256GCM", true)
iv <> tag <> cipher
end

def encryptAES256CCM(data, key, iv \\ :crypto.strong_rand_bytes(16)) do
{cipher, tag} = :crypto.crypto_one_time_aead(:aes_256_ccm, key, iv, data, "AES256CCM", true)
def encryptAES256CCM(data, key, iv) do
{cipher, tag} = :crypto.crypto_one_time_aead(:aes_256_ccm, key, iv, data, "AES256GCM", true)
iv <> tag <> cipher
end

def encryptAES128GCM(data, key, iv) do
{cipher, tag} = :crypto.crypto_one_time_aead(:aes_128_gcm, key, iv, data, "AES256GCM", true)
iv <> tag <> cipher
end

def encryptAES128CCM(data, key, iv) do
{cipher, tag} = :crypto.crypto_one_time_aead(:aes_128_ccm, key, iv, data, "AES256GCM", true)
iv <> tag <> cipher
end

# public API is ASN.1 based

def encrypt(crypto_codec, data, key, iv \\ :crypto.strong_rand_bytes(16))
def encrypt(:'id-aes256-ECB', data, key, iv), do: encryptAES256ECB(data, key, iv)
def encrypt(:'id-aes256-CBC', data, key, iv), do: encryptAES256CBC(data, key, iv)
def encrypt(:'id-aes256-GCM', data, key, iv), do: encryptAES256GCM(data, key, iv)
def encrypt(:'id-aes256-CCM', data, key, iv), do: encryptAES256CCM(data, key, iv)
def encrypt(:'id-aes128-GCM', data, key, iv), do: encryptAES128GCM(data, key, iv)
def encrypt(:'id-aes128-CCM', data, key, iv), do: encryptAES128CCM(data, key, iv)
def encrypt(:'id-aes128-CBC', data, key, iv), do: encryptAES128CBC(data, key, iv)
def encrypt(:'id-aes128-ECB', data, key, iv), do: encryptAES128ECB(data, key, iv)

def decrypt(crypto_codec, data, key, iv \\ :crypto.strong_rand_bytes(16))
def decrypt(:'id-aes256-ECB', data, key, iv), do: decryptAES256ECB(data, key, iv)
def decrypt(:'id-aes256-CBC', data, key, iv), do: decryptAES256CBC(data, key, iv)
def decrypt(:'id-aes256-GCM', data, key, iv), do: decryptAES256GCM(data, key, iv)
def decrypt(:'id-aes256-CCM', data, key, iv), do: decryptAES256CCM(data, key, iv)
def decrypt(:'id-aes128-GCM', data, key, iv), do: decryptAES128GCM(data, key, iv)
def decrypt(:'id-aes128-CCM', data, key, iv), do: decryptAES128CCM(data, key, iv)
def decrypt(:'id-aes128-CBC', data, key, iv), do: decryptAES128CBC(data, key, iv)
def decrypt(:'id-aes128-ECB', data, key, iv), do: decryptAES128ECB(data, key, iv)

def testSMIME() do
{:ok,base} = :file.read_file "priv/encrypted.txt" ; [_,s] = :string.split base, "\n\n"
Expand All @@ -74,8 +116,10 @@ defmodule CA.AES do
check_BrainPoolP512t1_GCM256(),
check_SECT571_GCM256(),
check_X448_GCM256(),
check_X448_GCM128(),
check_X448_CBC256(),
check_X448_ECB256(),
check_X448_CBC128(),
check_X448_ECB128(),
]
:ok
end
Expand All @@ -88,6 +132,7 @@ defmodule CA.AES do
maximK = privat "server.key"
maximS = :binary.part(shared(aliceP,maximK,scheme),0,32)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32)
true = aliceS == maximS
iv = :crypto.strong_rand_bytes(16)
x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv)
Expand All @@ -98,8 +143,9 @@ defmodule CA.AES do
scheme = :x25519
{aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme)
{maximP,maximK} = :crypto.generate_key(:ecdh, scheme)
maximS = shared(aliceP,maximK,scheme)
aliceS = shared(maximP,aliceK,scheme)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,32)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32)
true = aliceS == maximS
iv = :crypto.strong_rand_bytes(16)
x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv)
Expand All @@ -112,6 +158,7 @@ defmodule CA.AES do
{maximP,maximK} = :crypto.generate_key(:ecdh, scheme)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,32)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32)
true = aliceS == maximS
iv = :crypto.strong_rand_bytes(16)
x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv)
Expand All @@ -124,45 +171,49 @@ defmodule CA.AES do
{maximP,maximK} = :crypto.generate_key(:ecdh, scheme)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,32)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32)
true = aliceS == maximS
iv = :crypto.strong_rand_bytes(16)
x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv)
:ok
end

def check_BrainPoolP512t1_GCM256() do # BrainPoolP512t1
scheme = :brainpoolP512t1
def check_SECT571_GCM256() do # SECT571r1
scheme = :sect571r1
{aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme)
{maximP,maximK} = :crypto.generate_key(:ecdh, scheme)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,32)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32)
true = aliceS == maximS
iv = :crypto.strong_rand_bytes(16)
x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv)
:ok
end

def check_SECT571_GCM256() do # SECT571r1
scheme = :sect571r1
def check_X448_GCM256() do # X488
scheme = :x448
{aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme)
{maximP,maximK} = :crypto.generate_key(:ecdh, scheme)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,32)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32)
true = aliceS == maximS
iv = :crypto.strong_rand_bytes(16)
x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv)
:ok
end

def check_X448_GCM256() do # X488
def check_X448_GCM128() do # X488
scheme = :x448
{aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme)
{maximP,maximK} = :crypto.generate_key(:ecdh, scheme)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,32)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,16)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,16)
true = aliceS == maximS
iv = :crypto.strong_rand_bytes(16)
x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv)
x = encrypt(:'id-aes128-GCM', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes128-GCM', x, aliceS, iv)
:ok
end

Expand All @@ -172,19 +223,35 @@ defmodule CA.AES do
{maximP,maximK} = :crypto.generate_key(:ecdh, scheme)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,32)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32)
x = encrypt(:'id-aes256-CBC', "Success!", maximS)
"Success!" = decrypt(:'id-aes256-CBC', x, aliceS)
true = aliceS == maximS
iv = :crypto.strong_rand_bytes(16)
x = encrypt(:'id-aes256-CBC', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes256-CBC', x, aliceS, iv)
:ok
end

def check_X448_ECB256() do # X488
def check_X448_CBC128() do # X488
scheme = :x448
{aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme)
{maximP,maximK} = :crypto.generate_key(:ecdh, scheme)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,32)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32)
x = encrypt(:'id-aes256-ECB', "Success!", maximS)
"Success!" = decrypt(:'id-aes256-ECB', x, aliceS)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,16)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,16)
true = aliceS == maximS
iv = :crypto.strong_rand_bytes(16)
x = encrypt(:'id-aes128-CBC', "Success!", maximS, iv)
"Success!" = decrypt(:'id-aes128-CBC', x, aliceS, iv)
:ok
end

def check_X448_ECB128() do # X488
scheme = :x448
{aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme)
{maximP,maximK} = :crypto.generate_key(:ecdh, scheme)
maximS = :binary.part(shared(aliceP,maximK,scheme),0,16)
aliceS = :binary.part(shared(maximP,aliceK,scheme),0,16)
true = aliceS == maximS
x = encrypt(:'id-aes128-ECB', "Success!", maximS, "")
"Success!" = decrypt(:'id-aes128-ECB', x, aliceS, "")
:ok
end

Expand Down
2 changes: 1 addition & 1 deletion lib/ca.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ defmodule CA do
end

def convertOTPtoPKIX(cert) do
{:Certificate,{:TBSCertificate,:v3,a,ai,rdn,v,rdn2,{p1,{p21,p22,pki},p3},b,c,ext},ai,code} =
{:Certificate,{:TBSCertificate,:v3,a,ai,rdn,v,rdn2,{p1,{p21,p22,_pki},p3},b,c,ext},ai,code} =
:public_key.pkix_decode_cert(:public_key.pkix_encode(:OTPCertificate, cert, :otp), :plain)
{:Certificate,{:TBSCertificate,:v3,a,ai,CA.CAdES.unsubj(rdn),v,CA.CAdES.unsubj(rdn2),
{p1,{p21,p22,{:namedCurve,{1,3,132,0,34}}},p3},b,c,ext},ai,code}
Expand Down
2 changes: 1 addition & 1 deletion lib/cmc.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ defmodule CA.CMC do
case :gen_tcp.recv(socket, 0) do
{:ok, data} ->
{:ok, dec} = :'EnrollmentMessageSyntax-2009'.decode(:'PKIData', data)
{:PKIData, controlSequence, reqSequence, cmsSequence, otherMsgSequence} = dec
{:PKIData, _controlSequence, _reqSequence, cmsSequence, _otherMsgSequence} = dec
:io.format 'PKIData:~n~p~n', [dec]
__MODULE__.message(socket, cmsSequence)
loop(socket)
Expand Down
31 changes: 13 additions & 18 deletions lib/cmp.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,39 +17,34 @@ defmodule CA.CMP do
end

def baseKey(pass, salt, iter), do:
:lists.foldl(fn _, acc -> :crypto.hash(:sha256, acc) end, pass <> salt, :lists.seq(1,iter))
:lists.foldl(fn _, acc ->
:crypto.hash(:sha256, acc) end, pass <> salt,
:lists.seq(1,iter))

def validateProtection(header, body, code) do
{:PKIHeader, pvno, from, to, messageTime, {_,oid,{_,param}} = protectionAlg, senderKID, recipKID,
transactionID, senderNonce, recipNonce, freeText, generalInfo} = header
{oid, salt, owf, mac, counter} = protection(protectionAlg)
{:PKIHeader, _, _, _, _, protectionAlg, _, _, _, _, _, _, _} = header
{_oid, salt, _owf, _mac, counter} = protection(protectionAlg)
incomingProtection = CA."ProtectedPart"(header: header, body: body)
{:ok, bin} = :"PKIXCMP-2009".encode(:'ProtectedPart', incomingProtection)
verifyKey = baseKey(:application.get_env(:ca, :pbm, "0000"), salt, counter)
:crypto.mac(:hmac, CA.KDF.hs(:erlang.size(code)), verifyKey, bin)
end

def message(socket, header, {:ir, req} = body, code) do
{:PKIHeader, pvno, from, to, messageTime, {_,oid,{_,param}} = protectionAlg, senderKID, recipKID,
transactionID, senderNonce, recipNonce, freeText, generalInfo} = header
def message(_socket, _header, {:ir, req}, _) do
:lists.map(fn {:CertReqMsg, req, sig, code} ->
:io.format 'request: ~p~n', [req]
:io.format 'signature: ~p~n', [sig]
:io.format 'code: ~p~n', [code]
end, req)
end

def message(socket, header, {:genm, req} = body, code) do
{:PKIHeader, pvno, from, to, messageTime, {_,oid,{_,param}} = protectionAlg, senderKID, recipKID,
transactionID, senderNonce, recipNonce, freeText, generalInfo} = header
{:ok, parameters} = :"PKIXCMP-2009".decode(:'PBMParameter', param)
{:PBMParameter, salt, {_,owf,_}, counter, {_,mac,_} } = parameters
def message(_socket, _header, {:genm, req} = _body, _code) do
:io.format 'generalMessage: ~p~n', [req]
end

def message(socket, header, {:p10cr, csr} = body, code) do
{:PKIHeader, pvno, from, to, messageTime, protectionAlg, senderKID, recipKID,
transactionID, senderNonce, recipNonce, freeText, generalInfo} = header
{:PKIHeader, pvno, from, to, messageTime, protectionAlg, _senderKID, _recipKID,
transactionID, senderNonce, _recipNonce, _freeText, _generalInfo} = header
code = validateProtection(header, body, code)

{ca_key, ca} = CA.CSR.read_ca()
Expand All @@ -63,15 +58,15 @@ defmodule CA.CMP do
[ CA."CertResponse"(certReqId: 0,
certifiedKeyPair: CA."CertifiedKeyPair"(certOrEncCert:
{:certificate, {:x509v3PKCert, CA.convertOTPtoPKIX(cert)}}),
status: CA."PKIStatusInfo"(status: 1))])
status: CA."PKIStatusInfo"(status: 0))])

pkibody = {:cp, reply}
pkiheader = CA."PKIHeader"(sender: to, recipient: from, pvno: pvno, recipNonce: senderNonce,
transactionID: transactionID, protectionAlg: protectionAlg, messageTime: messageTime)
answer(socket, pkiheader, pkibody, validateProtection(pkiheader, pkibody, code))
end

def message(socket, header, {:certConf, statuses} = body, code) do
def message(socket, header, {:certConf, statuses}, code) do
{:PKIHeader, _, from, to, _, _, _, _, _, senderNonce, _, _, _} = header

:lists.map(fn {:CertStatus,bin,no,{:PKIStatusInfo, :accepted, _, _}} ->
Expand Down Expand Up @@ -108,10 +103,10 @@ defmodule CA.CMP do
def loop(socket) do
case :gen_tcp.recv(socket, 0) do
{:ok, data} ->
{{_,headers},asn} = :asn1rt_nif.decode_ber_tlv(data)
{{_,_headers},asn} = :asn1rt_nif.decode_ber_tlv(data)
[_,body] = :string.split asn, "\r\n\r\n", :all
{:ok,dec} = :'PKIXCMP-2009'.decode(:'PKIMessage', body)
{:PKIMessage, header, body, code, extra} = dec
{:PKIMessage, header, body, code, _extra} = dec
__MODULE__.message(socket, header, body, code)
loop(socket)
{:error, :closed} -> :exit
Expand Down

0 comments on commit 9e9de12

Please sign in to comment.