Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
D
Dnsmasq
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
Dnsmasq
Commits
86bec2d3
Commit
86bec2d3
authored
Jan 13, 2014
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Swap crypto library from openSSL to nettle.
parent
c3a04081
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
296 additions
and
504 deletions
+296
-504
Makefile
Makefile
+14
-14
src/blockdata.c
src/blockdata.c
+23
-24
src/dns-protocol.h
src/dns-protocol.h
+0
-18
src/dnsmasq.h
src/dnsmasq.h
+1
-2
src/dnssec-crypto.h
src/dnssec-crypto.h
+0
-83
src/dnssec-openssl.c
src/dnssec-openssl.c
+0
-316
src/dnssec.c
src/dnssec.c
+257
-46
src/option.c
src/option.c
+1
-1
No files found.
Makefile
View file @
86bec2d3
...
...
@@ -51,24 +51,24 @@ top!=pwd
# GNU make way.
top
?=
$(CURDIR)
dbus_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DBUS
$(PKG_CONFIG)
--cflags
dbus-1
`
dbus_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DBUS
$(PKG_CONFIG)
--libs
dbus-1
`
idn_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_IDN
$(PKG_CONFIG)
--cflags
libidn
`
idn_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_IDN
$(PKG_CONFIG)
--libs
libidn
`
ct_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_CONNTRACK
$(PKG_CONFIG)
--cflags
libnetfilter_conntrack
`
ct_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_CONNTRACK
$(PKG_CONFIG)
--libs
libnetfilter_conntrack
`
lua_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_LUASCRIPT
$(PKG_CONFIG)
--cflags
lua5.1
`
lua_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_LUASCRIPT
$(PKG_CONFIG)
--libs
lua5.1
`
sec_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DNSSEC
$(PKG_CONFIG)
--cflags
libcrypto
`
sec_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DNSSEC
$(PKG_CONFIG)
--libs
libcrypto
`
sunos_libs
=
`
if
uname
|
grep
SunOS
>
/dev/null 2>&1
;
then
echo
-lsocket
-lnsl
-lposix4
;
fi
`
dbus_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DBUS
$(PKG_CONFIG)
--cflags
dbus-1
`
dbus_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DBUS
$(PKG_CONFIG)
--libs
dbus-1
`
idn_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_IDN
$(PKG_CONFIG)
--cflags
libidn
`
idn_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_IDN
$(PKG_CONFIG)
--libs
libidn
`
ct_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_CONNTRACK
$(PKG_CONFIG)
--cflags
libnetfilter_conntrack
`
ct_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_CONNTRACK
$(PKG_CONFIG)
--libs
libnetfilter_conntrack
`
lua_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_LUASCRIPT
$(PKG_CONFIG)
--cflags
lua5.1
`
lua_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_LUASCRIPT
$(PKG_CONFIG)
--libs
lua5.1
`
nettle_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DNSSEC
$(PKG_CONFIG)
--cflags
nettle hogweed
`
nettle_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DNSSEC
$(PKG_CONFIG)
--libs
nettle hogweed
`
sunos_libs
=
`
if
uname
|
grep
SunOS
>
/dev/null 2>&1
;
then
echo
-lsocket
-lnsl
-lposix4
;
fi
`
version
=
-DVERSION
=
'\"`
$(top)
/bld/get-version
$(top)
`\"'
objs
=
cache.o rfc1035.o util.o option.o forward.o network.o
\
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o
\
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o
\
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o
\
domain.o dnssec.o
dnssec-openssl.o
blockdata.o
domain.o dnssec.o blockdata.o
hdrs
=
dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h
\
dns-protocol.h radv-protocol.h
...
...
@@ -76,8 +76,8 @@ hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
all
:
$(BUILDDIR)
@
cd
$(BUILDDIR)
&&
$(MAKE)
\
top
=
"
$(top)
"
\
build_cflags
=
"
$(version)
$(dbus_cflags)
$(idn_cflags)
$(ct_cflags)
$(lua_cflags)
$(
sec
_cflags)
"
\
build_libs
=
"
$(dbus_libs)
$(idn_libs)
$(ct_libs)
$(lua_libs)
$(sunos_libs)
$(
sec
_libs)
"
\
build_cflags
=
"
$(version)
$(dbus_cflags)
$(idn_cflags)
$(ct_cflags)
$(lua_cflags)
$(
nettle
_cflags)
"
\
build_libs
=
"
$(dbus_libs)
$(idn_libs)
$(ct_libs)
$(lua_libs)
$(sunos_libs)
$(
nettle
_libs)
"
\
-f
$(top)
/Makefile dnsmasq
mostly_clean
:
...
...
src/blockdata.c
View file @
86bec2d3
...
...
@@ -67,21 +67,6 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
return
ret
;
}
size_t
blockdata_walk
(
struct
blockdata
**
key
,
unsigned
char
**
p
,
size_t
cnt
)
{
if
(
*
p
==
NULL
)
*
p
=
(
*
key
)
->
key
;
else
if
(
*
p
==
(
*
key
)
->
key
+
KEYBLOCK_LEN
)
{
*
key
=
(
*
key
)
->
next
;
if
(
*
key
==
NULL
)
return
0
;
*
p
=
(
*
key
)
->
key
;
}
return
MIN
(
cnt
,
(
size_t
)((
*
key
)
->
key
+
KEYBLOCK_LEN
-
(
*
p
)));
}
void
blockdata_free
(
struct
blockdata
*
blocks
)
{
struct
blockdata
*
tmp
;
...
...
@@ -96,24 +81,38 @@ void blockdata_free(struct blockdata *blocks)
}
}
/*
copy blocks into data[], return 1 if data[] unchanged by so doing
*/
int
blockdata_retrieve
(
struct
blockdata
*
block
,
size_t
len
,
void
*
data
)
/*
if data == NULL, return pointer to static block of sufficient size
*/
void
*
blockdata_retrieve
(
struct
blockdata
*
block
,
size_t
len
,
void
*
data
)
{
size_t
blen
;
struct
blockdata
*
b
;
int
match
=
1
;
void
*
new
,
*
d
;
for
(
b
=
block
;
len
>
0
&&
b
;
b
=
b
->
next
)
static
unsigned
int
buff_len
=
0
;
static
unsigned
char
*
buff
=
NULL
;
if
(
!
data
)
{
if
(
len
>
buff_len
)
{
if
(
!
(
new
=
whine_malloc
(
len
)))
return
NULL
;
if
(
buff
)
free
(
buff
);
buff
=
new
;
}
data
=
buff
;
}
for
(
d
=
data
,
b
=
block
;
len
>
0
&&
b
;
b
=
b
->
next
)
{
blen
=
len
>
KEYBLOCK_LEN
?
KEYBLOCK_LEN
:
len
;
if
(
memcmp
(
data
,
b
->
key
,
blen
)
!=
0
)
match
=
0
;
memcpy
(
data
,
b
->
key
,
blen
);
data
+=
blen
;
memcpy
(
d
,
b
->
key
,
blen
);
d
+=
blen
;
len
-=
blen
;
}
return
match
;
return
data
;
}
#endif
src/dns-protocol.h
View file @
86bec2d3
...
...
@@ -136,24 +136,6 @@ struct dns_header {
(cp) += 4; \
}
#define CHECKED_GETCHAR(var, ptr, len) do { \
if ((len) < 1) return 0; \
var = *ptr++; \
(len) -= 1; \
} while (0)
#define CHECKED_GETSHORT(var, ptr, len) do { \
if ((len) < 2) return 0; \
GETSHORT(var, ptr); \
(len) -= 2; \
} while (0)
#define CHECKED_GETLONG(var, ptr, len) do { \
if ((len) < 4) return 0; \
GETLONG(var, ptr); \
(len) -= 4; \
} while (0)
#define CHECK_LEN(header, pp, plen, len) \
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
...
...
src/dnsmasq.h
View file @
86bec2d3
...
...
@@ -993,8 +993,7 @@ struct crec *cache_enumerate(int init);
#ifdef HAVE_DNSSEC
void
blockdata_report
(
void
);
struct
blockdata
*
blockdata_alloc
(
char
*
data
,
size_t
len
);
size_t
blockdata_walk
(
struct
blockdata
**
key
,
unsigned
char
**
p
,
size_t
cnt
);
int
blockdata_retrieve
(
struct
blockdata
*
block
,
size_t
len
,
void
*
data
);
void
*
blockdata_retrieve
(
struct
blockdata
*
block
,
size_t
len
,
void
*
data
);
void
blockdata_free
(
struct
blockdata
*
blocks
);
#endif
...
...
src/dnssec-crypto.h
deleted
100644 → 0
View file @
c3a04081
/* dnssec-crypto.h is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DNSSEC_CRYPTO_H
#define DNSSEC_CRYPTO_H
struct
blockdata
;
/*
* vtable for a signature verification algorithm.
*
* Each algorithm verifies that a certain signature over a (possibly non-contigous)
* array of data has been made with the specified key.
*
* Sample of usage:
*
* // First, set the signature we need to check. Notice: data is not copied
* // nor consumed, so the pointer must stay valid.
* alg->set_signature(sig, 16);
*
* // Second, get push the data through the corresponding digest algorithm;
* // data is consumed immediately, so the buffers can be freed or modified.
* digestalg_begin(alg->get_digestalgo());
* digestalg_add_data(buf1, 123);
* digestalg_add_data(buf2, 45);
* digestalg_add_data(buf3, 678);
* alg->set_digest(digestalg_final());
*
* // Third, verify if we got the correct key for this signature.
* alg->verify(key1, 16);
* alg->verify(key2, 16);
*/
typedef
struct
VerifyAlgCtx
VerifyAlgCtx
;
typedef
struct
{
int
digest_algo
;
int
(
*
verify
)(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key
,
unsigned
key_len
);
}
VerifyAlg
;
struct
VerifyAlgCtx
{
const
VerifyAlg
*
vtbl
;
unsigned
char
*
sig
;
size_t
siglen
;
unsigned
char
digest
[
64
];
/* TODO: if memory problems, use VLA */
};
int
verifyalg_supported
(
int
algo
);
VerifyAlgCtx
*
verifyalg_alloc
(
int
algo
);
void
verifyalg_free
(
VerifyAlgCtx
*
a
);
int
verifyalg_algonum
(
VerifyAlgCtx
*
a
);
/* Functions to calculate the digest of a key */
/* RFC4034 digest algorithms */
#define DIGESTALG_SHA1 1
#define DIGESTALG_SHA256 2
#define DIGESTALG_MD5 256
#define DIGESTALG_SHA512 257
int
digestalg_supported
(
int
algo
);
void
digestalg_begin
(
int
algo
);
void
digestalg_add_data
(
void
*
data
,
unsigned
len
);
void
digestalg_add_keydata
(
struct
blockdata
*
key
,
size_t
len
);
unsigned
char
*
digestalg_final
(
void
);
int
digestalg_len
(
void
);
#endif
/* DNSSEC_CRYPTO_H */
src/dnssec-openssl.c
deleted
100644 → 0
View file @
c3a04081
/* dnssec-openssl.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
#ifdef HAVE_DNSSEC
#include "dnssec-crypto.h"
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/err.h>
#include <string.h>
#define POOL_SIZE 1
static
union
_Pool
{
VerifyAlgCtx
ctx
;
}
Pool
[
POOL_SIZE
];
static
char
pool_used
=
0
;
static
void
print_hex
(
unsigned
char
*
data
,
unsigned
len
)
{
while
(
len
>
0
)
{
printf
(
"%02x"
,
*
data
++
);
--
len
;
}
printf
(
"
\n
"
);
}
static
int
keydata_to_bn
(
BIGNUM
*
ret
,
struct
blockdata
**
key_data
,
unsigned
char
**
p
,
unsigned
len
)
{
size_t
cnt
;
BIGNUM
temp
;
BN_init
(
ret
);
cnt
=
blockdata_walk
(
key_data
,
p
,
len
);
BN_bin2bn
(
*
p
,
cnt
,
ret
);
len
-=
cnt
;
*
p
+=
cnt
;
while
(
len
>
0
)
{
if
(
!
(
cnt
=
blockdata_walk
(
key_data
,
p
,
len
)))
return
0
;
BN_lshift
(
ret
,
ret
,
cnt
*
8
);
BN_init
(
&
temp
);
BN_bin2bn
(
*
p
,
cnt
,
&
temp
);
BN_add
(
ret
,
ret
,
&
temp
);
len
-=
cnt
;
*
p
+=
cnt
;
}
return
1
;
}
static
int
rsasha1_parse_key
(
BIGNUM
*
exp
,
BIGNUM
*
mod
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
unsigned
char
*
p
=
key_data
->
key
;
size_t
exp_len
,
mod_len
;
CHECKED_GETCHAR
(
exp_len
,
p
,
key_len
);
if
(
exp_len
==
0
)
CHECKED_GETSHORT
(
exp_len
,
p
,
key_len
);
if
(
exp_len
>=
key_len
)
return
0
;
mod_len
=
key_len
-
exp_len
;
return
keydata_to_bn
(
exp
,
&
key_data
,
&
p
,
exp_len
)
&&
keydata_to_bn
(
mod
,
&
key_data
,
&
p
,
mod_len
);
}
static
int
dsasha1_parse_key
(
BIGNUM
*
Q
,
BIGNUM
*
P
,
BIGNUM
*
G
,
BIGNUM
*
Y
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
unsigned
char
*
p
=
key_data
->
key
;
int
T
;
CHECKED_GETCHAR
(
T
,
p
,
key_len
);
return
keydata_to_bn
(
Q
,
&
key_data
,
&
p
,
20
)
&&
keydata_to_bn
(
P
,
&
key_data
,
&
p
,
64
+
T
*
8
)
&&
keydata_to_bn
(
G
,
&
key_data
,
&
p
,
64
+
T
*
8
)
&&
keydata_to_bn
(
Y
,
&
key_data
,
&
p
,
64
+
T
*
8
);
}
static
int
rsa_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
,
int
nid
,
int
dlen
)
{
int
validated
=
0
;
RSA
*
rsa
=
RSA_new
();
rsa
->
e
=
BN_new
();
rsa
->
n
=
BN_new
();
if
(
rsasha1_parse_key
(
rsa
->
e
,
rsa
->
n
,
key_data
,
key_len
)
&&
RSA_verify
(
nid
,
ctx
->
digest
,
dlen
,
ctx
->
sig
,
ctx
->
siglen
,
rsa
))
validated
=
1
;
RSA_free
(
rsa
);
return
validated
;
}
static
int
rsamd5_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
return
rsa_verify
(
ctx
,
key_data
,
key_len
,
NID_md5
,
16
);
}
static
int
rsasha1_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
return
rsa_verify
(
ctx
,
key_data
,
key_len
,
NID_sha1
,
20
);
}
static
int
rsasha256_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
return
rsa_verify
(
ctx
,
key_data
,
key_len
,
NID_sha256
,
32
);
}
static
int
rsasha512_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
return
rsa_verify
(
ctx
,
key_data
,
key_len
,
NID_sha512
,
64
);
}
static
int
dsasha1_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
static
unsigned
char
asn1_signature
[]
=
{
0x30
,
0x2E
,
// sequence
0x02
,
21
,
// large integer (21 bytes)
0x00
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
// R
0x02
,
21
,
// large integer (21 bytes)
0x00
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
// S
};
int
validated
=
0
;
/* A DSA signature is made of 2 bignums (R & S). We could parse them manually with BN_bin2bn(),
but OpenSSL does not have an API to verify a DSA signature given R and S, and insists
in having a ASN.1 BER sequence (as per RFC3279).
We prepare a hard-coded ASN.1 sequence, and just fill in the R&S numbers in it. */
memcpy
(
asn1_signature
+
5
,
ctx
->
sig
+
1
,
20
);
memcpy
(
asn1_signature
+
28
,
ctx
->
sig
+
21
,
20
);
DSA
*
dsa
=
DSA_new
();
dsa
->
q
=
BN_new
();
dsa
->
p
=
BN_new
();
dsa
->
g
=
BN_new
();
dsa
->
pub_key
=
BN_new
();
if
(
dsasha1_parse_key
(
dsa
->
q
,
dsa
->
p
,
dsa
->
g
,
dsa
->
pub_key
,
key_data
,
key_len
)
&&
DSA_verify
(
0
,
ctx
->
digest
,
20
,
asn1_signature
,
countof
(
asn1_signature
),
dsa
)
>
0
)
validated
=
1
;
DSA_free
(
dsa
);
return
validated
;
}
#define VALG_UNSUPPORTED() { \
0,0 \
}
/**/
#define VALG_VTABLE(alg, digest) { \
digest, \
alg ## _verify \
}
/**/
/* Updated registry that merges various RFCs:
https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xml */
static
const
VerifyAlg
valgs
[]
=
{
VALG_UNSUPPORTED
(),
/* 0: reserved */
VALG_VTABLE
(
rsamd5
,
DIGESTALG_MD5
),
/* 1: RSAMD5 */
VALG_UNSUPPORTED
(),
/* 2: DH */
VALG_VTABLE
(
dsasha1
,
DIGESTALG_SHA1
),
/* 3: DSA */
VALG_UNSUPPORTED
(),
/* 4: ECC */
VALG_VTABLE
(
rsasha1
,
DIGESTALG_SHA1
),
/* 5: RSASHA1 */
VALG_VTABLE
(
dsasha1
,
DIGESTALG_SHA1
),
/* 6: DSA-NSEC3-SHA1 */
VALG_VTABLE
(
rsasha1
,
DIGESTALG_SHA1
),
/* 7: RSASHA1-NSEC3-SHA1 */
VALG_VTABLE
(
rsasha256
,
DIGESTALG_SHA256
),
/* 8: RSASHA256 */
VALG_UNSUPPORTED
(),
/* 9: unassigned */
VALG_VTABLE
(
rsasha512
,
DIGESTALG_SHA512
),
/* 10: RSASHA512 */
VALG_UNSUPPORTED
(),
/* 11: unassigned */
VALG_UNSUPPORTED
(),
/* 12: ECC-GOST */
VALG_UNSUPPORTED
(),
/* 13: ECDSAP256SHA256 */
VALG_UNSUPPORTED
(),
/* 14: ECDSAP384SHA384 */
};
/* TODO: remove if we don't need this anymore
(to be rechecked if we ever remove OpenSSL) */
static
const
int
valgctx_size
[]
=
{
0
,
/* 0: reserved */
sizeof
(
VerifyAlgCtx
),
/* 1: RSAMD5 */
0
,
/* 2: DH */
sizeof
(
VerifyAlgCtx
),
/* 3: DSA */
0
,
/* 4: ECC */
sizeof
(
VerifyAlgCtx
),
/* 5: RSASHA1 */
sizeof
(
VerifyAlgCtx
),
/* 6: DSA-NSEC3-SHA1 */
sizeof
(
VerifyAlgCtx
),
/* 7: RSASHA1-NSEC3-SHA1 */
sizeof
(
VerifyAlgCtx
),
/* 8: RSASHA256 */
0
,
/* 9: unassigned */
sizeof
(
VerifyAlgCtx
),
/* 10: RSASHA512 */
0
,
/* 11: unassigned */
0
,
/* 12: ECC-GOST */
0
,
/* 13: ECDSAP256SHA256 */
0
,
/* 14: ECDSAP384SHA384 */
};
int
verifyalg_supported
(
int
algo
)
{
return
(
algo
<
countof
(
valgctx_size
)
&&
valgctx_size
[
algo
]
!=
0
);
}
VerifyAlgCtx
*
verifyalg_alloc
(
int
algo
)
{
int
i
;
VerifyAlgCtx
*
ret
=
0
;
if
(
pool_used
==
(
1
<<
POOL_SIZE
)
-
1
)
ret
=
whine_malloc
(
valgctx_size
[
algo
]);
else
for
(
i
=
0
;
i
<
POOL_SIZE
;
++
i
)
if
(
!
(
pool_used
&
(
1
<<
i
)))
{
ret
=
(
VerifyAlgCtx
*
)
&
Pool
[
i
];
pool_used
|=
1
<<
i
;
break
;
}
if
(
ret
)
ret
->
vtbl
=
&
valgs
[
algo
];
return
ret
;
}
void
verifyalg_free
(
VerifyAlgCtx
*
a
)
{
int
pool_idx
=
((
char
*
)
a
-
(
char
*
)
&
Pool
[
0
])
/
sizeof
(
Pool
[
0
]);
if
(
pool_idx
<
0
||
pool_idx
>=
POOL_SIZE
)
{
free
(
a
);
return
;
}
pool_used
&=
~
(
1
<<
pool_idx
);
}
int
verifyalg_algonum
(
VerifyAlgCtx
*
a
)
{
int
num
=
a
->
vtbl
-
valgs
;
if
(
num
<
0
||
num
>=
countof
(
valgs
))
return
-
1
;
return
num
;
}
static
EVP_MD_CTX
digctx
;
int
digestalg_supported
(
int
algo
)
{
return
(
algo
==
DIGESTALG_SHA1
||
algo
==
DIGESTALG_SHA256
||
algo
==
DIGESTALG_MD5
||
algo
==
DIGESTALG_SHA512
);
}
void
digestalg_begin
(
int
algo
)
{
EVP_MD_CTX_init
(
&
digctx
);
if
(
algo
==
DIGESTALG_SHA1
)
EVP_DigestInit_ex
(
&
digctx
,
EVP_sha1
(),
NULL
);
else
if
(
algo
==
DIGESTALG_SHA256
)
EVP_DigestInit_ex
(
&
digctx
,
EVP_sha256
(),
NULL
);
else
if
(
algo
==
DIGESTALG_SHA512
)
EVP_DigestInit_ex
(
&
digctx
,
EVP_sha512
(),
NULL
);
else
if
(
algo
==
DIGESTALG_MD5
)
EVP_DigestInit_ex
(
&
digctx
,
EVP_md5
(),
NULL
);
}
int
digestalg_len
()
{
return
EVP_MD_CTX_size
(
&
digctx
);
}
void
digestalg_add_data
(
void
*
data
,
unsigned
len
)
{
EVP_DigestUpdate
(
&
digctx
,
data
,
len
);
}
void
digestalg_add_keydata
(
struct
blockdata
*
key
,
size_t
len
)
{
size_t
cnt
;
unsigned
char
*
p
=
NULL
;
while
(
len
)
{
cnt
=
blockdata_walk
(
&
key
,
&
p
,
len
);
EVP_DigestUpdate
(
&
digctx
,
p
,
cnt
);
p
+=
cnt
;
len
-=
cnt
;
}
}
unsigned
char
*
digestalg_final
(
void
)
{
static
unsigned
char
digest
[
32
];
EVP_DigestFinal
(
&
digctx
,
digest
,
NULL
);
return
digest
;
}
#endif
/* HAVE_DNSSEC */
src/dnssec.c
View file @
86bec2d3
...
...
@@ -19,13 +19,210 @@
#ifdef HAVE_DNSSEC
#include "dnssec-crypto.h"
#include <nettle/rsa.h>
#include <nettle/dsa.h>
#include <nettle/nettle-meta.h>
#include <gmp.h>
#define SERIAL_UNDEF -100
#define SERIAL_EQ 0
#define SERIAL_LT -1
#define SERIAL_GT 1
/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
static
char
*
ds_digest_name
(
int
digest
)
{
switch
(
digest
)
{
case
1
:
return
"sha1"
;
case
2
:
return
"sha256"
;
case
3
:
return
"gosthash94"
;
case
4
:
return
"sha384"
;
default:
return
NULL
;
}
}
/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
static
char
*
algo_digest_name
(
int
algo
)
{
switch
(
algo
)
{
case
1
:
return
"md5"
;
case
3
:
return
"sha1"
;
case
5
:
return
"sha1"
;
case
6
:
return
"sha1"
;
case
7
:
return
"sha1"
;
case
8
:
return
"sha256"
;
case
10
:
return
"sha512"
;
case
12
:
return
"gosthash94"
;
case
13
:
return
"sha256"
;
case
14
:
return
"sha384"
;
default:
return
NULL
;
}
}
/* Find pointer to correct hash function in nettle library */
static
const
struct
nettle_hash
*
hash_find
(
char
*
name
)
{
int
i
;
if
(
!
name
)
return
NULL
;
for
(
i
=
0
;
nettle_hashes
[
i
];
i
++
)
{
if
(
strcmp
(
nettle_hashes
[
i
]
->
name
,
name
)
==
0
)
return
nettle_hashes
[
i
];
}
return
NULL
;
}
/* expand ctx and digest memory allocations if necessary and init hash function */
static
int
hash_init
(
const
struct
nettle_hash
*
hash
,
void
**
ctxp
,
unsigned
char
**
digestp
)
{
static
void
*
ctx
=
NULL
;
static
unsigned
char
*
digest
=
NULL
;
static
unsigned
int
ctx_sz
=
0
;
static
unsigned
int
digest_sz
=
0
;
void
*
new
;
if
(
ctx_sz
<
hash
->
context_size
)
{
if
(
!
(
new
=
whine_malloc
(
hash
->
context_size
)))
return
0
;
if
(
ctx
)
free
(
ctx
);
ctx
=
new
;
ctx_sz
=
hash
->
context_size
;
}
if
(
digest_sz
<
hash
->
digest_size
)
{
if
(
!
(
new
=
whine_malloc
(
hash
->
digest_size
)))
return
0
;
if
(
digest
)
free
(
digest
);
digest
=
new
;
digest_sz
=
hash
->
digest_size
;
}
*
ctxp
=
ctx
;
*
digestp
=
digest
;
hash
->
init
(
ctx
);
return
1
;
}
static
int
rsa_verify
(
struct
blockdata
*
key_data
,
unsigned
int
key_len
,
unsigned
char
*
sig
,
size_t
sig_len
,
unsigned
char
*
digest
,
int
algo
)
{
unsigned
char
*
p
;
size_t
exp_len
;
static
struct
rsa_public_key
*
key
=
NULL
;
static
mpz_t
sig_mpz
;
if
(
key
==
NULL
)
{
if
(
!
(
key
=
whine_malloc
(
sizeof
(
struct
rsa_public_key
))))
return
0
;
nettle_rsa_public_key_init
(
key
);
mpz_init
(
sig_mpz
);
}
if
((
key_len
<
3
)
||
!
(
p
=
blockdata_retrieve
(
key_data
,
key_len
,
NULL
)))
return
0
;
key_len
--
;
if
((
exp_len
=
*
p
++
)
==
0
)
{
GETSHORT
(
exp_len
,
p
);
key_len
-=
2
;
}
if
(
exp_len
>=
key_len
)
return
0
;
key
->
size
=
key_len
-
exp_len
;
mpz_import
(
key
->
e
,
exp_len
,
1
,
1
,
0
,
0
,
p
);
mpz_import
(
key
->
n
,
key
->
size
,
1
,
1
,
0
,
0
,
p
+
exp_len
);
mpz_import
(
sig_mpz
,
sig_len
,
1
,
1
,
0
,
0
,
sig
);
switch
(
algo
)
{
case
1
:
return
nettle_rsa_md5_verify_digest
(
key
,
digest
,
sig_mpz
);
case
5
:
case
7
:
return
nettle_rsa_sha1_verify_digest
(
key
,
digest
,
sig_mpz
);
case
8
:
return
nettle_rsa_sha256_verify_digest
(
key
,
digest
,
sig_mpz
);
case
10
:
return
nettle_rsa_sha512_verify_digest
(
key
,
digest
,
sig_mpz
);
}
return
0
;
}
static
int
dsa_verify
(
struct
blockdata
*
key_data
,
unsigned
int
key_len
,
unsigned
char
*
sig
,
size_t
sig_len
,
unsigned
char
*
digest
,
int
algo
)
{
unsigned
char
*
p
;
unsigned
int
t
;
static
struct
dsa_public_key
*
key
=
NULL
;
static
struct
dsa_signature
*
sig_struct
;
if
(
key
==
NULL
)
{
if
(
!
(
sig_struct
=
whine_malloc
(
sizeof
(
struct
dsa_signature
)))
||
!
(
key
=
whine_malloc
(
sizeof
(
struct
dsa_public_key
))))
return
0
;
nettle_dsa_public_key_init
(
key
);
nettle_dsa_signature_init
(
sig_struct
);
}
if
((
sig_len
<
41
)
||
!
(
p
=
blockdata_retrieve
(
key_data
,
key_len
,
NULL
)))
return
0
;
t
=
*
p
++
;
if
(
key_len
<
(
213
+
(
t
*
24
)))
return
0
;
mpz_import
(
key
->
q
,
20
,
1
,
1
,
0
,
0
,
p
);
p
+=
20
;
mpz_import
(
key
->
p
,
64
+
(
t
*
8
),
1
,
1
,
0
,
0
,
p
);
p
+=
64
+
(
t
*
8
);
mpz_import
(
key
->
g
,
64
+
(
t
*
8
),
1
,
1
,
0
,
0
,
p
);
p
+=
64
+
(
t
*
8
);
mpz_import
(
key
->
y
,
64
+
(
t
*
8
),
1
,
1
,
0
,
0
,
p
);
p
+=
64
+
(
t
*
8
);
mpz_import
(
sig_struct
->
r
,
20
,
1
,
1
,
0
,
0
,
sig
+
1
);
mpz_import
(
sig_struct
->
s
,
20
,
1
,
1
,
0
,
0
,
sig
+
21
);
(
void
)
algo
;
return
nettle_dsa_sha1_verify_digest
(
key
,
digest
,
sig_struct
);
}
static
int
verify
(
struct
blockdata
*
key_data
,
unsigned
int
key_len
,
unsigned
char
*
sig
,
size_t
sig_len
,
unsigned
char
*
digest
,
int
algo
)
{
switch
(
algo
)
{
case
1
:
case
5
:
case
7
:
case
8
:
case
10
:
return
rsa_verify
(
key_data
,
key_len
,
sig
,
sig_len
,
digest
,
algo
);
case
3
:
case
6
:
return
dsa_verify
(
key_data
,
key_len
,
sig
,
sig_len
,
digest
,
algo
);
}
return
0
;
}
/* Convert from presentation format to wire format, in place.
Also map UC -> LC.
Note that using extract_name to get presentation format
...
...
@@ -362,7 +559,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
if
(
type_covered
==
type
&&
check_date_range
(
sig_inception
,
sig_expiration
)
&&
verifyalg_supported
(
algo
)
&&
hash_find
(
algo_digest_name
(
algo
)
)
&&
labels
<=
name_labels
)
{
if
(
sigidx
==
sig_sz
)
...
...
@@ -404,9 +601,11 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* Now try all the sigs to try and find one which validates */
for
(
j
=
0
;
j
<
sigidx
;
j
++
)
{
unsigned
char
*
psav
;
int
i
,
wire_len
;
VerifyAlgCtx
*
alg
;
unsigned
char
*
psav
,
*
sig
;
int
i
,
wire_len
,
sig_len
;
const
struct
nettle_hash
*
hash
;
void
*
ctx
;
unsigned
char
*
digest
;
u32
nsigttl
;
p
=
sigs
[
j
];
...
...
@@ -427,16 +626,18 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
if
(
!
key
&&
!
(
crecp
=
cache_find_by_name
(
NULL
,
keyname
,
now
,
F_DNSKEY
)))
return
STAT_NEED_KEY
;
alg
=
verifyalg_alloc
(
algo
);
alg
->
sig
=
p
;
alg
->
siglen
=
rdlen
-
(
p
-
psav
);
sig
=
p
;
sig_len
=
rdlen
-
(
p
-
psav
);
if
(
!
(
hash
=
hash_find
(
algo_digest_name
(
algo
)))
||
!
hash_init
(
hash
,
&
ctx
,
&
digest
))
continue
;
nsigttl
=
htonl
(
orig_ttl
);
digestalg_begin
(
alg
->
vtbl
->
digest_algo
);
digestalg_add_data
(
psav
,
18
);
hash
->
update
(
ctx
,
18
,
psav
);
wire_len
=
to_wire
(
keyname
);
digestalg_add_data
(
keyname
,
wire_len
);
hash
->
update
(
ctx
,
(
unsigned
int
)
wire_len
,
(
unsigned
char
*
)
keyname
);
from_wire
(
keyname
);
for
(
i
=
0
;
i
<
rrsetidx
;
++
i
)
...
...
@@ -462,9 +663,9 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
}
wire_len
=
to_wire
(
name_start
);
digestalg_add_data
(
name_start
,
wire_len
);
digestalg_add_data
(
p
,
4
);
/* class and type */
digestalg_add_data
(
&
nsigttl
,
4
);
hash
->
update
(
ctx
,
(
unsigned
int
)
wire_len
,
(
unsigned
char
*
)
name_start
);
hash
->
update
(
ctx
,
4
,
p
);
/* class and type */
hash
->
update
(
ctx
,
4
,
(
unsigned
char
*
)
&
nsigttl
);
p
+=
8
;
/* skip class, type, ttl */
GETSHORT
(
rdlen
,
p
);
...
...
@@ -479,27 +680,27 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
for
(
len
=
0
;
(
seg
=
get_rdata
(
header
,
plen
,
end
,
name
,
&
cp
,
&
dp
))
!=
0
;
len
+=
seg
);
len
+=
end
-
cp
;
len
=
htons
(
len
);
digestalg_add_data
(
&
len
,
2
);
hash
->
update
(
ctx
,
2
,
(
unsigned
char
*
)
&
len
);
/* Now canonicalise again and digest. */
cp
=
p
;
dp
=
rr_desc
;
while
((
seg
=
get_rdata
(
header
,
plen
,
end
,
name
,
&
cp
,
&
dp
)))
digestalg_add_data
(
name
,
seg
);
hash
->
update
(
ctx
,
seg
,
(
unsigned
char
*
)
name
);
if
(
cp
!=
end
)
digestalg_add_data
(
cp
,
end
-
cp
);
hash
->
update
(
ctx
,
end
-
cp
,
cp
);
}
hash
->
digest
(
ctx
,
hash
->
digest_size
,
digest
);
/* namebuff used for workspace above, restore to leave unchanged on exit */
p
=
(
unsigned
char
*
)(
rrset
[
0
]);
extract_name
(
header
,
plen
,
&
p
,
name
,
1
,
0
);
memcpy
(
alg
->
digest
,
digestalg_final
(),
digestalg_len
());
if
(
key
)
{
if
(
algo_in
==
algo
&&
keytag_in
==
key_tag
&&
alg
->
vtbl
->
verify
(
alg
,
key
,
keylen
))
verify
(
key
,
keylen
,
sig
,
sig_len
,
digest
,
algo
))
return
STAT_SECURE
;
}
else
...
...
@@ -507,7 +708,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* iterate through all possible keys 4035 5.3.1 */
for
(;
crecp
;
crecp
=
cache_find_by_name
(
crecp
,
keyname
,
now
,
F_DNSKEY
))
if
(
crecp
->
addr
.
key
.
algo
==
algo
&&
crecp
->
addr
.
key
.
keytag
==
key_tag
&&
alg
->
vtbl
->
verify
(
alg
,
crecp
->
addr
.
key
.
keydata
,
crecp
->
uid
))
verify
(
crecp
->
addr
.
key
.
keydata
,
crecp
->
uid
,
sig
,
sig_len
,
digest
,
algo
))
return
STAT_SECURE
;
}
}
...
...
@@ -579,7 +780,6 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
psave
=
p
;
/* length at least covers flags, protocol and algo now. */
GETSHORT
(
flags
,
p
);
if
(
*
p
++
!=
3
)
return
STAT_INSECURE
;
...
...
@@ -606,30 +806,41 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
continue
;
for
(
recp1
=
crecp
;
recp1
;
recp1
=
cache_find_by_name
(
recp1
,
name
,
now
,
F_DS
))
if
(
recp1
->
addr
.
key
.
algo
==
algo
&&
recp1
->
addr
.
key
.
keytag
==
keytag
&&
(
flags
&
0x100
)
&&
/* zone key flag */
digestalg_supported
(
recp1
->
addr
.
key
.
digest
))
{
int
wire_len
=
to_wire
(
name
);
digestalg_begin
(
recp1
->
addr
.
key
.
digest
);
digestalg_add_data
(
name
,
wire_len
);
digestalg_add_data
((
char
*
)
psave
,
rdlen
);
{
void
*
ctx
;
unsigned
char
*
digest
,
*
ds_digest
;
const
struct
nettle_hash
*
hash
;
if
(
recp1
->
addr
.
key
.
algo
==
algo
&&
recp1
->
addr
.
key
.
keytag
==
keytag
&&
(
flags
&
0x100
)
&&
/* zone key flag */
(
hash
=
hash_find
(
ds_digest_name
(
recp1
->
addr
.
key
.
digest
)))
&&
hash_init
(
hash
,
&
ctx
,
&
digest
))
from_wire
(
name
);
if
(
recp1
->
uid
==
digestalg_len
()
&&
blockdata_retrieve
(
recp1
->
addr
.
key
.
keydata
,
recp1
->
uid
,
digestalg_final
())
&&
validate_rrset
(
now
,
header
,
plen
,
class
,
T_DNSKEY
,
name
,
keyname
,
key
,
rdlen
-
4
,
algo
,
keytag
))
{
struct
all_addr
a
;
valid
=
1
;
a
.
addr
.
keytag
=
keytag
;
log_query
(
F_KEYTAG
|
F_UPSTREAM
,
name
,
&
a
,
"DNSKEY keytag %u"
);
break
;
}
}
{
int
wire_len
=
to_wire
(
name
);
/* Note that digest may be different between DSs, so
we can't move this outside the loop. */
hash
->
update
(
ctx
,
(
unsigned
int
)
wire_len
,
(
unsigned
char
*
)
name
);
hash
->
update
(
ctx
,
(
unsigned
int
)
rdlen
,
psave
);
hash
->
digest
(
ctx
,
hash
->
digest_size
,
digest
);
from_wire
(
name
);
if
(
recp1
->
uid
==
(
int
)
hash
->
digest_size
&&
(
ds_digest
=
blockdata_retrieve
(
recp1
->
addr
.
key
.
keydata
,
recp1
->
uid
,
NULL
))
&&
memcmp
(
ds_digest
,
digest
,
recp1
->
uid
)
==
0
&&
validate_rrset
(
now
,
header
,
plen
,
class
,
T_DNSKEY
,
name
,
keyname
,
key
,
rdlen
-
4
,
algo
,
keytag
))
{
struct
all_addr
a
;
valid
=
1
;
a
.
addr
.
keytag
=
keytag
;
log_query
(
F_KEYTAG
|
F_UPSTREAM
,
name
,
&
a
,
"DNSKEY keytag %u"
);
break
;
}
}
}
}
if
(
valid
)
...
...
src/option.c
View file @
86bec2d3
...
...
@@ -3687,7 +3687,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
/* Upper bound on length */
new
->
key
=
opt_malloc
((
3
*
strlen
(
key64
)
/
4
));
new
->
key
=
opt_malloc
((
3
*
strlen
(
key64
)
/
4
)
+
1
);
unhide_metas
(
key64
);
if
((
new
->
keylen
=
parse_base64
(
key64
,
new
->
key
))
==
-
1
)
ret_err
(
_
(
"bad base64 in DNSKEY"
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment