Skip to content

Commit 0f6d332

Browse files
committed
Fixing for OpenSSL 3.0 support
1 parent 826552f commit 0f6d332

File tree

6 files changed

+228
-144
lines changed

6 files changed

+228
-144
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ Zlib_jll = "83775a58-1f1d-513f-b197-d71354ab007a"
2121

2222
[compat]
2323
BinDeps = "1.0"
24-
OpenSSL_jll = "1.1"
25-
julia = "1.6"
24+
OpenSSL_jll = "3"
25+
julia = "1.10"
2626

2727
[extras]
2828
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

src/CosCrypt.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function store_key(s::SecHandler, cfn::CosName,
55
data::Tuple{UInt32, SecretBuffer})
66
skey = SecretBuffer!(read(s.skey_path, 32))
77
iv = SecretBuffer!(read(s.iv_path, 16))
8-
cctx = CipherContext("aes_256_cbc", skey, iv, true)
8+
cctx = CipherContext("AES-256-CBC", skey, iv, true)
99
shred!(skey); shred!(iv)
1010

1111
perm, key = data
@@ -21,7 +21,7 @@ function get_key(s::SecHandler, cfn::CosName)
2121

2222
skey = SecretBuffer!(read(s.skey_path, 32))
2323
iv = SecretBuffer!(read(s.iv_path, 16))
24-
cctx = CipherContext("aes_256_cbc", skey, iv, false)
24+
cctx = CipherContext("AES-256-CBC", skey, iv, false)
2525
shred!(skey); shred!(iv)
2626

2727
perm, c = permkey
@@ -95,7 +95,7 @@ function algo01(h::SecHandler, params::CryptParams,
9595
n != kc.size && error("Invalid encryption key length")
9696
seekend(kc); write(kc, numarr); write(kc, genarr)
9797
!isRC4 && write(kc, AES_SUFFIX)
98-
mdctx = DigestContext("md5")
98+
mdctx = DigestContext("MD5")
9999
update!(mdctx, kc)
100100
return close(mdctx)
101101
end
@@ -104,7 +104,7 @@ function algo01(h::SecHandler, params::CryptParams,
104104
iv = SecretBuffer!(isRC4 ? UInt8[] :
105105
isencrypt ? crypto_random(16) : data[1:16])
106106
try
107-
cctx = CipherContext(isRC4 ? "rc4" : "aes_128_cbc", key, iv, isencrypt)
107+
cctx = CipherContext(isRC4 ? "RC4" : "AES-128-CBC", key, iv, isencrypt)
108108
d = (isRC4 || isencrypt) ? update!(cctx, data) :
109109
update!(cctx, (@view data[17:end]))
110110
append!(d, close(cctx))
@@ -119,7 +119,7 @@ function algo01a(h::SecHandler, params::CryptParams,
119119
perm, key = get_key(h, params)
120120
iv = SecretBuffer!(isencrypt ? crypto_random(16) : data[1:16])
121121
try
122-
cctx = CipherContext("aes_256_cbc", key, iv, isencrypt)
122+
cctx = CipherContext("AES-256-CBC", key, iv, isencrypt)
123123
d = isencrypt ? update!(cctx, data) : update!(cctx, (@view data[17:end]))
124124
append!(d, close(cctx))
125125
return d

src/LibCrypto.jl

Lines changed: 94 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using OpenSSL_jll: libcrypto
22

3-
using Base: SecretBuffer, SecretBuffer!
3+
using Base: SecretBuffer, SecretBuffer!, cconvert
44
import Base: copy
55

66
export
@@ -160,17 +160,20 @@ end
160160

161161
function get_date_from_utctime(d::String)
162162
# Remove fraction seconds if there
163-
d[end] == 'Z' || error(E_INVALID_DATE)
163+
d = strip(d)
164+
endswith(d, 'Z') || error(E_INVALID_DATE)
164165
a = split(d, '.')
165166
length(a) > 1 && (d = a[1]*"Z")
166167
pfx = length(d) == 15 ? "D:" :
167168
parse(Int, d[1:2]) < 50 ? "D:20" : "D:19"
168169
return CDDate(pfx*d)
169170
end
170171

171-
read_cddate(bio::BIO) =
172-
bio |> read |> pointer |> unsafe_string |> get_date_from_utctime
173-
172+
function read_cddate(bio::BIO)
173+
data = read(bio)
174+
d = transcode(String, data)
175+
return get_date_from_utctime(d)
176+
end
174177
#====
175178
176179
DigestContext
@@ -236,34 +239,62 @@ end
236239
CipherContext
237240
238241
====#
242+
abstract type CipherContext end
243+
244+
set_padding(_::CipherContext, _) = nothing
245+
246+
Base.reset(_::CipherContext) = nothing
247+
248+
Base.close(_::CipherContext) = UInt8[]
249+
250+
init(_::CipherContext, _::SecretBuffer, _::SecretBuffer, _::Bool) = nothing
251+
252+
update!(_::CipherContext, indata::AbstractVector{UInt8}) = indata
253+
254+
function CipherContext(algo::String, key::SecretBuffer,
255+
iv::SecretBuffer, isencrypt::Bool)
256+
return algo == "RC4" ?
257+
CipherContextRC4(key) :
258+
CipherContextImpl(algo, key, iv, isencrypt)
259+
end
260+
261+
mutable struct CipherContextRC4 <: CipherContext
262+
key::SecretBuffer
263+
end
264+
265+
function init(ctx::CipherContextRC4, key::SecretBuffer,
266+
_::SecretBuffer, _::Bool)
267+
ctx.key = key
268+
return nothing
269+
end
270+
271+
function update!(ctx::CipherContextRC4, indata::AbstractVector{UInt8})
272+
rc4((@view ctx.key.data[1:ctx.key.size]), indata)
273+
end
239274

240-
mutable struct CipherContext
275+
mutable struct CipherContextImpl <: CipherContext
241276
data::Ptr{Cvoid}
242277
ca::Ptr{Cvoid}
243-
function CipherContext(algo::String, key::SecretBuffer,
278+
function CipherContextImpl(algo::String, key::SecretBuffer,
244279
iv::SecretBuffer, isencrypt::Bool)
245-
ca = ccall((:EVP_get_cipherbyname, libcrypto), Ptr{Cvoid},
246-
(Ptr{Cstring}, ), pointer(algo))
247-
if ca == C_NULL
248-
ca = (algo == "aes_128_cbc") ?
249-
ccall((:EVP_aes_128_cbc, libcrypto), Ptr{Cvoid}, ()) :
250-
(algo == "aes_256_cbc") ?
251-
ccall((:EVP_aes_256_cbc, libcrypto), Ptr{Cvoid}, ()) :
252-
(algo == "aes_256_ecb") ?
253-
ccall((:EVP_aes_256_ecb, libcrypto), Ptr{Cvoid}, ()) :
254-
error("Unable to find message digest algorithm "*algo)
255-
end
280+
properties = "provider=default"
281+
ca = ccall((:EVP_CIPHER_fetch, libcrypto), Ptr{Cvoid},
282+
(Ptr{Cvoid}, Ptr{Cstring}, Ptr{Cstring}),
283+
C_NULL, pointer(algo), pointer(properties))
284+
ca == C_NULL && error("Unable to find cipher algorithm "*algo)
256285
data = ccall((:EVP_CIPHER_CTX_new, libcrypto), Ptr{Cvoid}, ())
257286
data == C_NULL && error("Unable to create cipher context")
258287
this = new(data, ca)
259-
finalizer(x->ccall((:EVP_CIPHER_CTX_free, libcrypto), Cvoid,
260-
(Ptr{Cvoid}, ), x.data), this)
288+
finalizer(this) do x
289+
ccall((:EVP_CIPHER_CTX_free, libcrypto), Cvoid, (Ptr{Cvoid}, ), x.data)
290+
ccall((:EVP_CIPHER_free, libcrypto), Cvoid, (Ptr{Cvoid}, ), x.ca)
291+
end
261292
init(this, key, iv, isencrypt)
262293
return this
263294
end
264295
end
265296

266-
function init(ctx::CipherContext, key::SecretBuffer,
297+
function init(ctx::CipherContextImpl, key::SecretBuffer,
267298
iv::SecretBuffer, isencrypt::Bool)
268299
enc = Cint(isencrypt ? 1 : 0)
269300
piv = iv.size > 0 ? pointer(iv.data) : C_NULL
@@ -278,21 +309,21 @@ function init(ctx::CipherContext, key::SecretBuffer,
278309
return nothing
279310
end
280311

281-
function set_padding(ctx::CipherContext, pad_size::Int)
312+
function set_padding(ctx::CipherContextImpl, pad_size::Int)
282313
ret = ccall((:EVP_CIPHER_CTX_set_padding, libcrypto), Cint,
283314
(Ptr{Cvoid}, Cint), ctx.data, Cint(pad_size))
284315
openssl_error(ret)
285316
end
286317

287-
function Base.reset(ctx::CipherContext)
318+
function Base.reset(ctx::CipherContextImpl)
288319
ret = ccall((:EVP_CIPHER_CTX_reset, libcrypto), Cint,
289320
(Ptr{Cvoid}, ), ctx.data)
290321
openssl_error(ret)
291322
end
292323

293324
const EVP_MAX_BLOCK_LENGTH = Cint(32)
294325

295-
function update!(ctx::CipherContext, indata::AbstractVector{UInt8})
326+
function update!(ctx::CipherContextImpl, indata::AbstractVector{UInt8})
296327
inlen = Cint(length(indata))
297328
out, outlen = Vector{UInt8}(undef, inlen + EVP_MAX_BLOCK_LENGTH),
298329
Ref(inlen + EVP_MAX_BLOCK_LENGTH)
@@ -303,11 +334,10 @@ function update!(ctx::CipherContext, indata::AbstractVector{UInt8})
303334
return resize!(out, outlen[])
304335
end
305336

306-
update!(ctx::CipherContext, s::SecretBuffer) =
337+
update!(ctx::CipherContextImpl, s::SecretBuffer) =
307338
update!(ctx, (@view s.data[1:s.size]))
308339

309-
310-
function Base.close(ctx::CipherContext)
340+
function Base.close(ctx::CipherContextImpl)
311341
c_value = Vector{UInt8}(undef, EVP_MAX_BLOCK_LENGTH)
312342
c_len = Ref(EVP_MAX_BLOCK_LENGTH)
313343
ret = ccall((:EVP_CipherFinal_ex, libcrypto), Cint,
@@ -342,7 +372,7 @@ mutable struct CertStore
342372

343373
ret = ccall((:X509_STORE_load_locations, libcrypto), Cint,
344374
(Ptr{Cvoid}, Ptr{Cstring}, Ptr{Cstring}),
345-
store, transcode(UInt8, cacerts), C_NULL)
375+
store, pointer(cacerts), C_NULL)
346376
openssl_error(ret)
347377

348378
ccall((:X509_STORE_set_default_paths, libcrypto),
@@ -879,7 +909,7 @@ function read_pkcs12(fn::AbstractString, pw::SecretBuffer)
879909
ret = ccall((:PKCS12_parse, libcrypto), Cint,
880910
(Ptr{Cvoid}, Ptr{Cstring},
881911
Ptr{Ptr{Cvoid}}, Ptr{Ptr{Cvoid}}, Ptr{Ptr{Cvoid}}),
882-
p12, pointer(pw.data), xkey, xcert, xca)
912+
p12, cconvert(Cstring, pw), xkey, xcert, xca)
883913
openssl_error(ret)
884914
return Cert(xcert[]), PKey(xkey[])
885915
end
@@ -927,3 +957,38 @@ function decrypt(ci::CMSContentInfo, key::PKey, cert::Cert,
927957
return nothing
928958
end
929959
end
960+
961+
# Adapted from https://gist.github.com/rverton/a44fc8ca67ab9ec32089 for 1-indexing
962+
963+
const N = 256
964+
965+
function ksa(K::AbstractVector{UInt8})
966+
lk = length(K)
967+
S = [UInt8(i) for i=0:(N-1)]
968+
j = 0
969+
lk == 0 && return S
970+
for i = 0:(N-1)
971+
ik = i % lk
972+
j = (j + S[i+1] + K[ik+1]) % N
973+
S[i+1], S[j+1] = S[j+1], S[i+1]
974+
end
975+
return S
976+
end
977+
978+
function prga(S, plaintext::AbstractVector{UInt8})
979+
i = j = 0
980+
len = length(plaintext)
981+
ciphertext = copy(plaintext)
982+
for n = 0:(len-1)
983+
i = (i + 1) % N
984+
j = (j + S[i+1]) % N
985+
986+
S[i+1], S[j+1] = S[j+1], S[i+1]
987+
t = (S[i+1] + S[j+1]) % N
988+
989+
ciphertext[n+1] = xor(S[t+1], plaintext[n+1])
990+
end
991+
return ciphertext
992+
end
993+
994+
rc4(key::AbstractVector{UInt8}, plaintext::AbstractVector{UInt8}) = prga(ksa(key), plaintext)

src/PDDoc.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -537,10 +537,12 @@ function pdDocValidateSignatures(doc::PDDoc; export_certs=false)
537537
pd_validate_signature(doc, sig)
538538
d = sig[2]
539539
push!(ret, d)
540-
cis = d[:certs]
541-
for ci in cis
542-
key = (ci[:subject], ci[:issuer])
543-
get!(certmap, key, ci[:text])
540+
if haskey(d, :certs)
541+
cis = d[:certs]
542+
for ci in cis
543+
key = (ci[:subject], ci[:issuer])
544+
get!(certmap, key, ci[:text])
545+
end
544546
end
545547
end
546548
export_certs || return ret

src/StdSecHandler.jl

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ end
5959

6060
function algo02(h::StdSecHandler, password::SecretBuffer)
6161
# step a, b
62-
mdctx = DigestContext("md5")
62+
mdctx = DigestContext("MD5")
6363
shred!(get_padded_pw(password)) do pw
6464
update!(mdctx, pw)
6565
end
@@ -118,7 +118,7 @@ function algo02a(h::StdSecHandler, pw::SecretBuffer, isowner::Bool)
118118
end
119119
iv = SecretBuffer!(fill(0x00, 16))
120120
try
121-
cctx = CipherContext("aes_256_cbc", ik, iv, false)
121+
cctx = CipherContext("AES-256-CBC", ik, iv, false)
122122
set_padding(cctx, 0)
123123
de = isowner ? oe : ue
124124
fek = SecretBuffer!(update!(cctx, de))
@@ -147,7 +147,7 @@ function algo02b(h::StdSecHandler, password::SecretBuffer,
147147
end
148148
# b
149149
key = SecretBuffer!(k[1:16]); iv = SecretBuffer!(k[17:32])
150-
cctx = CipherContext("aes_128_cbc", key, iv, true)
150+
cctx = CipherContext("AES-128-CBC", key, iv, true)
151151
shred!(key); shred!(iv)
152152
set_padding(cctx, 0)
153153
e = update!(cctx, k1)
@@ -176,7 +176,7 @@ end
176176

177177
function algo03p_a_d(h::StdSecHandler, password::SecretBuffer)
178178
# a, b
179-
mdctx = DigestContext("md5")
179+
mdctx = DigestContext("MD5")
180180
shred!(get_padded_pw(password)) do pw
181181
update!(mdctx, pw)
182182
end
@@ -199,7 +199,7 @@ algo03(h::StdSecHandler, password::Vector{UInt8}) = error(E_NOT_IMPLEMENTED)
199199
function algo04(h::StdSecHandler, password::SecretBuffer)
200200
key = SecretBuffer!(algo02(h, password))
201201
iv = SecretBuffer!(UInt8[])
202-
cctx = CipherContext("rc4", key, iv, true)
202+
cctx = CipherContext("RC4", key, iv, true)
203203
shred!(iv)
204204
u = update!(cctx, PASSWD_PADDING)
205205
c = close(cctx)
@@ -216,24 +216,25 @@ function modkey(key::SecretBuffer, f::Int)
216216
end
217217

218218
function algo05p_a_e(h::StdSecHandler, password::SecretBuffer)
219-
key = SecretBuffer!(algo02(h, password))
219+
b = algo02(h, password)
220+
key = SecretBuffer!(b)
220221
iv = SecretBuffer!(UInt8[])
221222
try
222-
mdctx = DigestContext("md5")
223+
mdctx = DigestContext("MD5")
223224
update!(mdctx, PASSWD_PADDING)
224225
update!(mdctx, h.id)
225226
md = close(mdctx)
226-
cctx = CipherContext("rc4", key, iv, true)
227+
cctx = CipherContext("RC4", key, iv, true)
227228
c = update!(cctx, md)
228229
append!(c, close(cctx))
229230

230231
for i = 1:19
231232
reset(cctx)
232233
shred!(modkey(key, i)) do tkey
233234
init(cctx, tkey, iv, true)
235+
c = update!(cctx, c)
236+
append!(c, close(cctx))
234237
end
235-
c = update!(cctx, c)
236-
append!(c, close(cctx))
237238
end
238239
return c, key
239240
finally
@@ -256,15 +257,15 @@ function algo07(h::StdSecHandler, password::SecretBuffer)
256257
# b
257258
iv = SecretBuffer!(UInt8[])
258259
try
259-
cctx = CipherContext("rc4", key, iv, false)
260+
cctx = CipherContext("RC4", key, iv, false)
260261
od, count = h.o, (h.r == 2 ? 0 : 19)
261262
for i = count:-1:0
262263
reset(cctx)
263264
shred!(modkey(key, i)) do tkey
264265
init(cctx, tkey, iv, false)
266+
od = update!(cctx, od)
267+
append!(od, close(cctx))
265268
end
266-
od = update!(cctx, od)
267-
append!(od, close(cctx))
268269
end
269270
return shred!(upw -> algo06(h, upw), SecretBuffer!(od))
270271
finally
@@ -299,7 +300,7 @@ end
299300
function algo13(h::StdSecHandler, fek::SecretBuffer)
300301
perms = h.perms
301302
cctx = shred!(SecretBuffer!(fill(0x00, 16))) do iv
302-
CipherContext("aes_256_ecb", fek, iv, false)
303+
CipherContext("AES-256-ECB", fek, iv, false)
303304
end
304305
set_padding(cctx, 0)
305306
dperm = update!(cctx, perms)

0 commit comments

Comments
 (0)