Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 136 additions & 2 deletions src/OpenSSL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ Error handling:
"""

export TLSv12ClientMethod, TLSv12ServerMethod,
SSLStream, BigNum, EvpPKey, RSA, DSA, Asn1Time, X509Name, StackOf, X509Certificate,
SSLStream, BigNum, EvpPKey, RSA, DSA, EC, ECBuiltinCurve, Asn1Time, X509Name, StackOf, X509Certificate,
X509Request, X509Store, X509Attribute, X509Extension, P12Object, EvpDigestContext, EvpCipherContext,
EvpEncNull, EvpBlowFishCBC, EvpBlowFishECB, EvpBlowFishCFB, EvpBlowFishOFB, EvpAES128CBC,
EvpAES128ECB, EvpAES128CFB, EvpAES128OFB, EvpMDNull, EvpMD2, EvpMD5, EvpSHA1, EvpDSS1,
encrypt_init, cipher, add_extension, add_extensions, decrypt_init, digest_init, digest_update, digest_final,
digest, random_bytes, rsa_generate_key, dsa_generate_key, add_entry, sign_certificate, sign_request, adjust,
digest, random_bytes, rsa_generate_key, dsa_generate_key, ec_generate_key, ec_builtin_curves, add_entry, sign_certificate, sign_request, adjust,
add_cert, unpack, eof, isreadable, iswritable, bytesavailable, read, unsafe_write, connect,
get_peer_certificate, free, HTTP2_ALPN, UPDATE_HTTP2_ALPN, version

Expand Down Expand Up @@ -1400,6 +1400,124 @@ function dsa_generate_key(; bits::Int32=Int32(1024))::DSA
return dsa
end



"""
EC structure.
"""
mutable struct EC
ec::Ptr{Cvoid}

function EC()
ec = ccall(
(:EC_KEY_new, libcrypto),
Ptr{Cvoid},
())
if ec == C_NULL
throw(OpenSSLError())
end

ec = new(ec)
finalizer(free, ec)

return ec
end

function EC(p::Ptr{Cvoid})
ec = new(p)
finalizer(free, ec)
return ec
end
end

function free(ec::EC)
ccall(
(:EC_KEY_free, libcrypto),
Cvoid,
(EC,),
ec)

ec.ec = C_NULL
return nothing
end

"""
Generate EC key pair.
"""
function ec_generate_key(nid::Int32)::EC
ecptr = ccall(
(:EC_KEY_new_by_curve_name, libcrypto),
Ptr{Cvoid},
(Cint,), nid)
if ecptr == C_NULL
throw(OpenSSLError())
end
return EC(ecptr)
end

function ec_generate_key(curvename::AbstractString)::EC
found = filter(x -> x.name == curvename, ec_builtin_curves())
if length(found) == 0
error("No built in curve with name '$curvename' exists")
end
nid = first(found).id
return ec_generate_key(nid)
end


struct ECBuiltinCurve
id::Int32
name::String
comment::String
end

struct _EC_builtin_curve
nid::Cint
comment::Ptr{Cchar}
end

"""
Get all the builtin curves. Use id or name when calling ec_generate_key.
"""
function ec_builtin_curves()
curves = Vector{ECBuiltinCurve}()
ncurves = ccall(
(:EC_get_builtin_curves, libcrypto),
Csize_t,
(Ptr{Cvoid}, Csize_t),
C_NULL, 0)

builtin_curve_ids = Vector{_EC_builtin_curve}(undef, ncurves)

GC.@preserve builtin_curve_ids ncurves begin
if ccall(
(:EC_get_builtin_curves, libcrypto),
Csize_t,
(Ptr{Cvoid}, Csize_t),
pointer(builtin_curve_ids),
ncurves) != ncurves
throw(OpenSSLError())
end
for ecbc in builtin_curve_ids
name = ""
nid = convert(Int32, ecbc.nid)
comment = String(unsafe_string(ecbc.comment))
namecptr = ccall(
(:OSSL_EC_curve_nid2name, libcrypto),
Ptr{Cchar},
(Cint,),
ecbc.nid)
if namecptr != C_NULL
name = String(unsafe_string(namecptr))
end
push!(curves, ECBuiltinCurve(nid, name, comment))
end
end
return curves
end



"""
OpenSSL BIOMethod.
"""
Expand Down Expand Up @@ -1809,6 +1927,22 @@ mutable struct EvpPKey
return evp_pkey
end

function EvpPKey(ec::EC)::EvpPKey
evp_pkey = EvpPKey()

if ccall(
(:EVP_PKEY_assign, libcrypto),
Cint, (EvpPKey, Cint, EC),
evp_pkey,
EVP_PKEY_EC,
ec) != 1
throw(OpenSSLError())
end

ec.ec = C_NULL
return evp_pkey
end

"""
Creates a EvpPKey from PEM string.
"""
Expand Down
16 changes: 15 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ end

x509_server_cert = OpenSSL.get_peer_certificate(ssl)

@test String(x509_server_cert.issuer_name) == "/C=US/O=Let's Encrypt/CN=R3"
@test String(x509_server_cert.issuer_name) == "/C=US/O=Let's Encrypt/CN=R11"
@test String(x509_server_cert.subject_name) == "/CN=httpbingo.julialang.org"

request_str = "GET /status/200 HTTP/1.1\r\nHost: httpbingo.julialang.org\r\nUser-Agent: curl\r\nAccept: */*\r\n\r\n"
Expand Down Expand Up @@ -564,6 +564,20 @@ end
dsa = dsa_generate_key()
end

@testset "EC" begin
curves = ec_builtin_curves()
if length(curves) > 0
builtincurve = first(curves)
eckey = EvpPKey(ec_generate_key(builtincurve.id))
@test eckey.key_type == OpenSSL.EVP_PKEY_EC
free(eckey)

eckey = EvpPKey(ec_generate_key(builtincurve.name))
@test eckey.key_type == OpenSSL.EVP_PKEY_EC
free(eckey)
end
end

@testset "X509Attribute" begin
attr = X509Attribute()
free(attr)
Expand Down
Loading