Current section
Files
Jump to
Current section
Files
lib/services/est.ex
defmodule CA.EST do
@moduledoc "CA/EST/CMP HTTPS/HTTP server."
@profiles [ "secp256k1", "secp384r1", "secp521r1" ]
@templates [ "ocsp", "ipsec", "bgp", "eap", "cap", "sip", "cmc", "scvp", "ssh", "tls" ]
@classes [ "ca", "ra", "server", "client", "human", "program" ]
# Authority PKI X.509 CMP over CoAP RFC 9482
# Authority PKI X.509 CMP over HTTP RFC 9483
# Authority PKI X.509 EST over HTTPS RFC 7030
# [1] https://www.rfc-editor.org/rfc/rfc9483
# [2] https://www.rfc-editor.org/rfc/rfc7030
# [3] https://www.ietf.org/archive/id/draft-ietf-lamps-rfc7030-csrattrs-07.html
use Plug.Router
plug :match
plug :dispatch
plug Plug.Parsers, parsers: [:json], json_decoder: Jason
def start_link(opt) do
:logger.info "Classes: ~tp", [@classes]
:logger.info "Templates: ~tp", [@templates]
:logger.info "Profiles: ~tp", [@profiles]
Bandit.start_link(opt)
end
def child_spec(opt) do
%{
id: EST,
start: {CA.EST, :start_link, [opt]},
type: :supervisor,
restart: :permanent
}
end
get "/.well-known/est/:operation" do CA.EST.Get.get(conn, "CA", [], [], action(operation)) end
get "/.well-known/est/:profile/:operation" do CA.EST.Get.get(conn, "CA", curve(profile), template(profile), action(operation)) end
get "/.well-known/cmp/p/:profile/:operation" do CA.EST.Get.get(conn, "CA", curve(profile), template(profile), action(operation)) end
post "/.well-known/est/:operation" do CA.EST.Post.post(conn, "CA", [], [], action(operation)) end
post "/.well-known/est/:profile/:operation" do CA.EST.Post.post(conn, "CA", curve(profile), template(profile), action(operation)) end
post "/.well-known/cmp/p/:profile/:operation" do CA.EST.Post.post(conn, "CA", curve(profile), template(profile), action(operation)) end
def curve(profile) do
case String.split(profile,"-") do
[curve|_] when curve in @profiles -> curve
_ -> [] end
end
def template(profile) do
case String.split(profile,"-") do
[_,template|_] when template in @classes -> template
_ -> [] end
end
def action("ca") do "CA" end
def action("cacerts") do "CMS" end
def action("csrattrs") do "ABAC" end
def action("simpleenroll") do "ENROLL" end
def action("simplereenroll") do "RE-ENROLL" end
def action("serverkeygen") do "KEYGEN" end
def action("fullcmc") do "CMC" end
def action("initialization") do "INIT" end
def action("certification") do "CERT" end
def action("keyupdate") do "KEYUP" end
def action("pkcs10") do "PKCS-10" end
def action("revocation") do "REVOKE" end
def action("getcacerts") do "CMS" end
def action("getrootupdate") do "ROOT" end
def action("getcertreqtemplate") do "TEMPLATE" end
def action("getcrls") do "CRL" end
def action("nested") do "NESTED" end
def action("ir") do "INIT" end
def action("cr") do "CERT" end
def action("kur") do "KEYUP" end
def action("p10") do "PKCS-10" end
def action("rr") do "REVOKE" end
def action("crts") do "CMS" end
def action("rcu") do "ROOT" end
def action("att") do "TEMPLATE" end
def action("crls") do "CRL" end
def action("nest") do "NESTED" end
def csrattributes() do
{:ok, bin} = :"EST".encode(:CsrAttrs, [
oid: CA.AT.oid(:"id-at-challengePassword"),
oid: CA.X962.oid(:"id-ds-ecdsa-with-SHA384"),
attribute: {:Attribute, CA.X962.oid(:"id-kt-ecPublicKey"), [CA.CE.objectIdentifier(CA.ALG.oid(:secp384r1))] },
attribute: {:Attribute, CA.AT.oid(:rsaEncryption), [CA.CE.integer(4096)]},
attribute: {:Attribute, CA.AT.oid(:"id-at-extensionRequest"), [
CA.CE.extension({:Extension, CA.CE.oid(:"id-ce-keyUsage"), true, CA.CE.keyUsage([:digitalSignature, :keyCertSign, :cRLSign])}),
CA.CE.extension({:Extension, CA.CE.oid(:"id-ce-basicConstraints"), true, CA.CE.basicConstraints()}),
CA.CE.extension({:Extension, CA.CE.oid(:"id-ce-extKeyUsage"), false,
CA.CE.extendedKeyUsage([ CA.KP.oid(:"id-kp-serverAuth"),
CA.KP.oid(:"id-kp-clientAuth"),
CA.KP.oid(:"id-kp-codeSigning"),
CA.KP.oid(:"id-kp-emailProtection") ])})
]}
])
bin
end
match _ do send_resp(conn, 404, "Please refer to https://authority.erp.uno for more information.\n") end
def encode(x) do
case Jason.encode(x) do
{:ok, bin} -> bin
{:error, _} -> ""
end |> Jason.Formatter.pretty_print
end
end