sync code with last improvements from OpenBSD

This commit is contained in:
purplerain 2023-09-28 08:40:30 +00:00
parent 4de47ea988
commit f463301edc
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
142 changed files with 4045 additions and 1295 deletions

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: fopen.3,v 1.32 2015/01/15 19:20:59 schwarze Exp $
.\" $OpenBSD: fopen.3,v 1.33 2023/09/28 01:51:00 jsg Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -31,7 +31,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd $Mdocdate: January 15 2015 $
.Dd $Mdocdate: September 28 2023 $
.Dt FOPEN 3
.Os
.Sh NAME
@ -269,22 +269,12 @@ and
functions first appeared in
.At v7 .
.Pp
Opening a file for both reading and writing has been possible since
.Bx 2 .
.Pp
Support for the
.Dq e
and
.Dq x
mode letters appeared in
.Ox 5.7 .
.Sh AUTHORS
.An Dennis Ritchie
originally implemented
.Fn fopen
in PDP-11 assembler.
.An Keith Sklower
first implemented read-write access.
.Sh CAVEATS
Proper code using
.Fn fdopen

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: getc.3,v 1.16 2022/09/11 06:38:11 jmc Exp $
.\" $OpenBSD: getc.3,v 1.17 2023/09/28 01:51:00 jsg Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -31,7 +31,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd $Mdocdate: September 11 2022 $
.Dd $Mdocdate: September 28 2023 $
.Dt GETC 3
.Os
.Sh NAME
@ -126,13 +126,6 @@ and
.Fn fgetc
in
.At v7 .
.Sh AUTHORS
.An Dennis Ritchie
originally implemented
.Fn getc
and
.Fn getw
in PDP-11 assembler.
.Sh BUGS
Since
.Dv EOF

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: access.2,v 1.26 2022/08/02 01:23:23 jsg Exp $
.\" $OpenBSD: access.2,v 1.27 2023/09/28 01:51:00 jsg Exp $
.\" $NetBSD: access.2,v 1.7 1995/02/27 12:31:44 cgd Exp $
.\"
.\" Copyright (c) 1980, 1991, 1993
@ -30,7 +30,7 @@
.\"
.\" @(#)access.2 8.2 (Berkeley) 4/1/94
.\"
.Dd $Mdocdate: August 2 2022 $
.Dd $Mdocdate: September 28 2023 $
.Dt ACCESS 2
.Os
.Sh NAME
@ -232,11 +232,6 @@ The
.Fn faccessat
function appeared in
.Ox 5.0 .
.Sh AUTHORS
.An Ken Thompson
first implemented the
.Fn access
kernel function in C.
.Sh CAVEATS
.Fn access
and

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ec_ameth.c,v 1.43 2023/08/21 09:52:30 tb Exp $ */
/* $OpenBSD: ec_ameth.c,v 1.45 2023/09/24 08:08:54 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
@ -87,37 +87,135 @@ eckey_param_free(int ptype, void *pval)
}
static int
eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
eckey_get_curve_name(const EC_KEY *eckey, int *nid)
{
const EC_GROUP *group;
int nid;
if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
*nid = NID_undef;
if ((group = EC_KEY_get0_group(eckey)) == NULL) {
ECerror(EC_R_MISSING_PARAMETERS);
return 0;
}
if (EC_GROUP_get_asn1_flag(group) &&
(nid = EC_GROUP_get_curve_name(group))) {
/* we have a 'named curve' => just set the OID */
*ppval = OBJ_nid2obj(nid);
*pptype = V_ASN1_OBJECT;
} else {
/* explicit parameters */
ASN1_STRING *pstr = NULL;
pstr = ASN1_STRING_new();
if (!pstr)
return 0;
pstr->length = i2d_ECParameters(ec_key, &pstr->data);
if (pstr->length <= 0) {
ASN1_STRING_free(pstr);
ECerror(ERR_R_EC_LIB);
return 0;
}
*ppval = pstr;
*pptype = V_ASN1_SEQUENCE;
}
if (EC_GROUP_get_asn1_flag(group) != 0)
*nid = EC_GROUP_get_curve_name(group);
return 1;
}
static int
eckey_to_explicit_params(EC_KEY *eckey, void **out_val)
{
ASN1_STRING *astr = NULL;
unsigned char *params = NULL;
int params_len = 0;
int ret = 0;
*out_val = NULL;
if ((params_len = i2d_ECParameters(eckey, &params)) <= 0) {
ECerror(ERR_R_EC_LIB);
params_len = 0;
goto err;
}
if ((astr = ASN1_STRING_new()) == NULL)
goto err;
ASN1_STRING_set0(astr, params, params_len);
params = NULL;
params_len = 0;
*out_val = astr;
astr = NULL;
ret = 1;
err:
freezero(params, params_len);
ASN1_STRING_free(astr);
return ret;
}
static int
eckey_from_explicit_params(const ASN1_STRING *astr, EC_KEY **out_eckey)
{
const unsigned char *params = astr->data;
int params_len = astr->length;
EC_KEY_free(*out_eckey);
if ((*out_eckey = d2i_ECParameters(NULL, &params, params_len)) == NULL) {
ECerror(EC_R_DECODE_ERROR);
return 0;
}
return 1;
}
static int
eckey_to_object(const EC_KEY *eckey, void **out_val)
{
int nid = NID_undef;
*out_val = NULL;
if (!eckey_get_curve_name(eckey, &nid))
return 0;
if ((*out_val = OBJ_nid2obj(nid)) == NULL)
return 0;
return 1;
}
static int
eckey_from_object(const ASN1_OBJECT *aobj, EC_KEY **out_eckey)
{
int nid;
*out_eckey = NULL;
if ((nid = OBJ_obj2nid(aobj)) == NID_undef)
return 0;
if ((*out_eckey = EC_KEY_new_by_curve_name(nid)) == NULL)
return 0;
return 1;
}
static int
eckey_to_params(EC_KEY *eckey, int *out_type, void **out_val)
{
int nid;
*out_type = NID_undef;
*out_val = NULL;
if (!eckey_get_curve_name(eckey, &nid))
return 0;
if (nid == NID_undef) {
*out_type = V_ASN1_SEQUENCE;
return eckey_to_explicit_params(eckey, out_val);
} else {
*out_type = V_ASN1_OBJECT;
return eckey_to_object(eckey, out_val);
}
}
static int
eckey_from_params(int ptype, const void *pval, EC_KEY **out_eckey)
{
*out_eckey = NULL;
if (ptype == V_ASN1_SEQUENCE)
return eckey_from_explicit_params(pval, out_eckey);
if (ptype == V_ASN1_OBJECT)
return eckey_from_object(pval, out_eckey);
ECerror(EC_R_DECODE_ERROR);
return 0;
}
static int
eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
{
@ -129,7 +227,7 @@ eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
int key_len = 0;
int ret = 0;
if (!eckey_param2type(&ptype, &pval, eckey)) {
if (!eckey_to_params(eckey, &ptype, &pval)) {
ECerror(ERR_R_EC_LIB);
goto err;
}
@ -154,54 +252,6 @@ eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
return ret;
}
static EC_KEY *
eckey_type2param(int ptype, const void *pval)
{
EC_GROUP *group = NULL;
EC_KEY *eckey = NULL;
if (ptype == V_ASN1_SEQUENCE) {
const ASN1_STRING *pstr = pval;
const unsigned char *pm = NULL;
int pmlen;
pm = pstr->data;
pmlen = pstr->length;
if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) {
ECerror(EC_R_DECODE_ERROR);
goto ecerr;
}
} else if (ptype == V_ASN1_OBJECT) {
const ASN1_OBJECT *poid = pval;
/*
* type == V_ASN1_OBJECT => the parameters are given by an
* asn1 OID
*/
if ((eckey = EC_KEY_new()) == NULL) {
ECerror(ERR_R_MALLOC_FAILURE);
goto ecerr;
}
group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
if (group == NULL)
goto ecerr;
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
if (EC_KEY_set_group(eckey, group) == 0)
goto ecerr;
} else {
ECerror(EC_R_DECODE_ERROR);
goto ecerr;
}
EC_GROUP_free(group);
return eckey;
ecerr:
EC_KEY_free(eckey);
EC_GROUP_free(group);
return NULL;
}
static int
eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
{
@ -210,37 +260,38 @@ eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
int ptype, pklen;
EC_KEY *eckey = NULL;
X509_ALGOR *palg;
int ret = 0;
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
return 0;
goto err;
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
eckey = eckey_type2param(ptype, pval);
if (!eckey_from_params(ptype, pval, &eckey))
goto err;
if (!eckey) {
ECerror(ERR_R_EC_LIB);
return 0;
}
/* We have parameters now set public key */
if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
ECerror(EC_R_DECODE_ERROR);
goto ecerr;
goto err;
}
EVP_PKEY_assign_EC_KEY(pkey, eckey);
return 1;
if (!EVP_PKEY_assign_EC_KEY(pkey, eckey))
goto err;
eckey = NULL;
ecerr:
if (eckey)
EC_KEY_free(eckey);
return 0;
ret = 1;
err:
EC_KEY_free(eckey);
return ret;
}
static int
eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
{
int r;
const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), *pb = EC_KEY_get0_public_key(b->pkey.ec);
const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec);
const EC_POINT *pb = EC_KEY_get0_public_key(b->pkey.ec);
int r;
r = EC_POINT_cmp(group, pa, pb, NULL);
if (r == 0)
@ -263,9 +314,7 @@ eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
return 0;
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
eckey = eckey_type2param(ptype, pval);
if (!eckey)
if (!eckey_from_params(ptype, pval, &eckey))
goto ecliberr;
/* We have parameters now set private key */
@ -331,7 +380,7 @@ eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
flags = EC_KEY_get_enc_flags(eckey);
if (!eckey_param2type(&ptype, &pval, eckey)) {
if (!eckey_to_params(eckey, &ptype, &pval)) {
ECerror(EC_R_DECODE_ERROR);
goto err;
}
@ -416,7 +465,9 @@ ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
static int
ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{
const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), *group_b = EC_KEY_get0_group(b->pkey.ec);
const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec);
const EC_GROUP *group_b = EC_KEY_get0_group(b->pkey.ec);
if (EC_GROUP_cmp(group_a, group_b, NULL))
return 0;
else
@ -685,8 +736,7 @@ ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, X509_ALGOR *alg,
if (!EC_KEY_set_group(ecpeer, grp))
goto err;
} else {
ecpeer = eckey_type2param(atype, aval);
if (!ecpeer)
if (!eckey_from_params(atype, aval, &ecpeer))
goto err;
}

View file

@ -0,0 +1,134 @@
.\" $OpenBSD: ASIdentifiers_new.3,v 1.7 2023/09/27 08:46:46 tb Exp $
.\"
.\" Copyright (c) 2021 Theo Buehler <tb@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 27 2023 $
.Dt ASIDENTIFIERS_NEW 3
.Os
.Sh NAME
.Nm ASIdentifiers_new ,
.Nm ASIdentifiers_free ,
.Nm d2i_ASIdentifiers ,
.Nm i2d_ASIdentifiers
.Nd RFC 3779 autonomous system identifier delegation extensions
.Sh SYNOPSIS
.In openssl/x509v3.h
.Ft ASIdentifiers *
.Fo ASIdentifiers_new
.Fa "void"
.Fc
.Ft void
.Fo ASIdentifiers_free
.Fa "ASIdentifiers *asid"
.Fc
.Ft ASIdentifiers *
.Fo d2i_ASIdentifiers
.Fa "ASIdentifiers **asid"
.Fa "const unsigned char **in"
.Fa "long len"
.Fc
.Ft int
.Fo i2d_ASIdentifiers
.Fa "ASIdentifiers *asid"
.Fa "unsigned char **out"
.Fc
.Sh DESCRIPTION
RFC 3779 defines two X.509v3 certificate extensions that allow the
delegation of
IP address blocks and autonomous system (AS) identifiers
from the issuer to the subject of the certificate.
An
.Vt ASIdentifiers
object contains collections of individual AS numbers and
ranges of AS numbers to be delegated.
.Pp
.Fn ASIdentifiers_new
allocates and initializes a new, empty
.Vt ASIdentifiers
object that can be populated with
.Xr X509v3_asid_add_id_or_range 3 .
See
.Xr ASRange_new 3
for implementation details.
.Pp
.Fn ASIdentifiers_free
frees
.Fa asid
including any data contained in it.
If
.Fa asid
is
.Dv NULL ,
no action occurs.
.Pp
.Fn d2i_ASIdentifiers
and
.Fn i2d_ASIdentifiers
decode and encode ASN.1
.Vt ASIdentifiers
objects as defined in RFC 3779, section 3.2.3.1.
For details about the semantics, examples, caveats, and bugs, see
.Xr ASN1_item_d2i 3 .
In order for the encoding produced by
.Fn i2d_ASIdentifiers
to conform to RFC 3779,
.Fa asid
must be in
.Dq canonical form ,
see
.Xr X509v3_asid_canonize 3 .
.Sh RETURN VALUES
.Fn ASIdentifiers_new
returns a new
.Vt ASIdentifiers
object or
.Dv NULL
on if an error occurs.
.Pp
.Fn d2i_ASIdentifiers
returns an
.Vt ASIdentifiers
object or
.Dv NULL
on if a decoding or memory allocation error occurs.
.Pp
.Fn i2d_ASIdentifiers
returns the number of bytes successfully encoded
or a value <= 0 if an error occurs.
.Sh SEE ALSO
.Xr ASRange_new 3 ,
.Xr crypto 3 ,
.Xr IPAddressRange_new 3 ,
.Xr X509_new 3 ,
.Xr X509v3_asid_add_id_or_range 3 ,
.Xr X509v3_asid_inherits 3
.Sh STANDARDS
RFC 3779: X.509 Extensions for IP Addresses and AS Identifiers:
.Bl -dash -compact
.It
section 3: Autonomous System Identifier Delegation Extension
.El
.Pp
RFC 7020: The Internet Numbers Registry System
.Pp
RFC 7249: Internet Numbers Registries
.Sh HISTORY
These functions first appeared in OpenSSL 0.9.8e
and have been available since
.Ox 7.1 .
.Sh BUGS
There are no corresponding functions for the RFC 3779
IP address blocks delegation extension represented by
.Vt IPAddrBlocks .

View file

@ -0,0 +1,416 @@
.\" $OpenBSD: ASRange_new.3,v 1.5 2023/09/27 08:46:46 tb Exp $
.\"
.\" Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 27 2023 $
.Dt ASRANGE_NEW 3
.Os
.Sh NAME
.Nm ASRange_new ,
.Nm ASRange_free ,
.Nm d2i_ASRange ,
.Nm i2d_ASRange ,
.Nm ASIdOrRange_new ,
.Nm ASIdOrRange_free ,
.Nm d2i_ASIdOrRange ,
.Nm i2d_ASIdOrRange ,
.Nm ASIdentifierChoice_new ,
.Nm ASIdentifierChoice_free ,
.Nm d2i_ASIdentifierChoice ,
.Nm i2d_ASIdentifierChoice
.Nd RFC 3779 autonomous system identifiers and ranges
.Sh SYNOPSIS
.In openssl/x509v3.h
.Ft "ASRange *"
.Fn ASRange_new void
.Ft void
.Fn ASRange_free "ASRange *asrange"
.Ft ASRange *
.Fo d2i_ASRange
.Fa "ASRange **asrange"
.Fa "const unsigned char **der_in"
.Fa "long length"
.Fc
.Ft int
.Fo i2d_ASRange
.Fa "ASRange *asrange"
.Fa "unsigned char **der_out"
.Fc
.Ft "ASIdOrRange *"
.Fn ASIdOrRange_new void
.Ft void
.Fn ASIdOrRange_free "ASIdOrRange *aor"
.Ft ASIdOrRange *
.Fo d2i_ASIdOrRange
.Fa "ASIdOrRange **aor"
.Fa "const unsigned char **der_in"
.Fa "long length"
.Fc
.Ft int
.Fo i2d_ASIdOrRange
.Fa "ASIdOrRange *aor"
.Fa "unsigned char **der_out"
.Fc
.Ft "ASIdentifierChoice *"
.Fn ASIdentifierChoice_new void
.Ft void
.Fn ASIdentifierChoice_free "ASIdentifierChoice *aic"
.Ft ASIdentifierChoice *
.Fo d2i_ASIdentifierChoice
.Fa "ASIdentifierChoice **aic"
.Fa "const unsigned char **der_in"
.Fa "long length"
.Fc
.Ft int
.Fo i2d_ASIdentifierChoice
.Fa "ASIdentifierChoice *aic"
.Fa "unsigned char **der_out"
.Fc
.Sh DESCRIPTION
.Vt ASRange ,
.Vt ASIdOrRange ,
and
.Vt ASIdentifierChoice
are building blocks of the
.Vt ASIdentifiers
type representing the RFC 3779
autonomous system identifier delegation extension.
.Pp
All
.Vt ASN1_INTEGER Ns s
in this manual should be representable as unsigned 32-bit integers.
The API performs no corresponding checks.
The library provides no convenient way of setting the value of an
.Vt ASN1_INTEGER
directly.
A detour via a
.Vt BIGNUM
or a string is unavoidable.
To retrieve the value of an
.Vt ASN1_INTEGER ,
use
.Xr ASN1_INTEGER_get_uint64 3 .
.Pp
The
.Vt ASRange
type defined in RFC 3779 section 3.2.3.8 is implemented as
.Bd -literal -offset indent
typedef struct ASRange_st {
ASN1_INTEGER *min;
ASN1_INTEGER *max;
} ASRange;
.Ed
.Pp
It represents the closed range [min,max] of AS identifiers between
.Fa min
and
.Fa max ,
where
.Fa min
should be strictly smaller than
.Fa max .
.Pp
.Fn ASRange_new
allocates a new
.Vt ASRange
object with allocated, empty
.Fa min
and
.Fa max ,
thus representing the invalid range [0,0].
.Pp
.Fn ASRange_free
frees
.Fa asrange
including any data contained in it.
If
.Fa asrange
is
.Dv NULL ,
no action occurs.
.Pp
The
.Vt ASIdOrRange
type defined in RFC 3779 section 3.2.3.5 is implemented as
.Bd -literal -offset indent
typedef struct ASIdOrRange_st {
int type;
union {
ASN1_INTEGER *id;
ASRange *range;
} u;
} ASIdOrRange;
.Ed
.Pp
representing an individual AS identifier or a range.
When populating an
.Vt ASIdOrRange
object by hand, its
.Fa type
should be set to
.Dv ASIdOrRange_id
or
.Dv ASIdOrRange_range
to indicate which member of the union
.Fa u
is valid.
.Pp
.Fn ASIdOrRange_new
returns a new
.Vt ASIdOrRange
object with invalid type and
.Dv NULL
members of the union
.Fa u .
.Pp
.Fn ASIdOrRange_free
frees
.Fa aor
including any data contained in it,
provided
.Fa type
is set correctly.
If
.Fa asrange
is
.Dv NULL ,
no action occurs.
.Pp
In order to express a list of AS identifiers and ranges,
RFC 3779 section 3.2.3.4
uses an ASN.1 SEQUENCE,
which is implemented via a
.Xr STACK_OF 3
construction over
.Vt ASIdOrRange :
.Bd -literal -offset indent
typedef STACK_OF(ASIdOrRange) ASIdOrRanges;
.Ed
.Pp
Since an
.Vt ASIdOrRanges
object should be sorted in a specific way (see
.Xr X509v3_asid_canonize 3 Ns ),
a comparison function is needed for a correct instantiation
with
.Xr sk_new 3 .
The
.Fn ASIdOrRange_cmp
function is not directly exposed and not easily accessible
from outside the library,
and it is non-trivial to implement.
It is therefore discouraged to use
.Vt ASIdOrRanges
objects that are not part of an
.Vt ASIdentifiers
object.
.Pp
The
.Dq inherit
marker from RFC 3779 section 3.2.3.3 is implemented as
.Vt ASN1_NULL .
It has no dedicated type or API and can be instantiated with
.Xr ASN1_NULL_new 3 .
.Pp
The
.Vt ASIdentifierChoice
type defined in RFC 3779 section 3.2.3.2 is implemented as
.Bd -literal -offset indent
typedef struct ASIdentifierChoice_st {
int type;
union {
ASN1_NULL *inherit;
ASIdOrRanges *asIdsOrRanges;
} u;
} ASIdentifierChoice;
.Ed
.Pp
where the
.Fa type
member should be set to
.Dv ASIdentifierChoice_inherit
or
.Dv ASIdentifierChoice_asIdsOrRanges
to indicate whether a given
.Vt ASIdentifierChoice
object represents an inherited list or an explicit list.
.Pp
.Fn ASIdentifierChoice_new
returns a new
.Vt ASIdentifierChoice
object with invalid type and
.Dv NULL
members of the union
.Fa u .
.Pp
.Fn ASIdentifierChoice_free
frees
.Fa aic
including any data contained in it,
provided
.Fa type
is set correctly.
.Pp
The
.Vt ASIdentifiers
type defined in RFC 3779 section 3.2.3.1 is implemented as
.Bd -literal -offset indent
typedef struct ASIdentifiers_st {
ASIdentifierChoice *asnum;
ASIdentifierChoice *rdi;
} ASIdentifiers;
.Ed
.Pp
It should be instantiated with
.Xr ASIdentifiers_new 3
and populated with
.Xr X509v3_asid_add_id_or_range 3 .
.Pp
.Fn d2i_ASRange ,
.Fn i2d_ASRange ,
.Fn d2i_ASIdOrRange ,
.Fn i2d_ASIdOrRange ,
.Fn d2i_ASIdentifierChoice ,
and
.Fn i2d_ASIdentifierChoice
decode and encode ASN.1
.Vt ASRange ,
.Vt ASIdOrRange ,
and
.Vt ASIdentifierChoice
objects.
For details about the semantics, examples, caveats, and bugs, see
.Xr ASN1_item_d2i 3 .
In order for the encoding produced by
.Fn i2d_ASRange
to be correct,
.Fa min
must be strictly less than
.Fa max .
Similarly for
.Fn i2d_ASIdOrRange
and an
.Fa ASIdOrRange
object of
.Fa type
.Dv ASIdOrRange_range .
.Sh RETURN VALUES
.Fn ASRange_new
returns a new
.Vt ASRange
object with allocated, empty members, or
.Dv NULL
if an error occurs.
.Pp
.Fn ASIdOrRange_new
returns a new, empty
.Vt ASIdOrRange
object or
.Dv NULL
if an error occurs.
.Pp
.Fn ASIdentifierChoice_new
returns a new, empty
.Vt ASIdentifierChoice
object or
.Dv NULL
if an error occurs.
.Pp
The encoding functions
.Fn d2i_ASRange ,
.Fn d2i_ASIdOrRange ,
and
.Fn d2i_ASIdentifierChoice
return an
.Vt ASRange ,
an
.Vt ASIdOrRange ,
or an
.Vt ASIdentifierChoice ,
object, respectively,
or
.Dv NULL
if an error occurs.
.Pp
The encoding functions
.Fn i2d_ASRange ,
.Fn i2d_ASIdOrRange ,
and
.Fn i2d_ASIdentifierChoice
return the number of bytes successfully encoded
or a value <= 0 if an error occurs.
.Sh SEE ALSO
.Xr ASIdentifiers_new 3 ,
.Xr BN_set_word 3 ,
.Xr BN_to_ASN1_INTEGER 3 ,
.Xr crypto 3 ,
.Xr IPAddressRange_new 3 ,
.Xr s2i_ASN1_INTEGER 3 ,
.Xr X509_new 3 ,
.Xr X509v3_asid_add_id_or_range 3
.Sh STANDARDS
RFC 3779: X.509 Extensions for IP Addresses and AS Identifiers:
.Bl -dash -compact
.It
section 3.2.3: Syntax
.It
section 3.2.3.1: Type ASIdentifiers
.It
section 3.2.3.2: Elements asnum, rdi, and Type ASIdentifierChoice
.It
section 3.2.3.3: Element inherit
.It
section 3.2.3.4: Element asIdsOrRanges
.It
section 3.2.3.5: Type ASIdOrRange
.It
section 3.2.3.6: Element id
.It
section 3.2.3.7: Element range
.It
section 3.2.3.8: Type ASRange
.It
section 3.2.3.9: Elements min and max
.El
.Sh HISTORY
These functions first appeared in OpenSSL 0.9.8e
and have been available since
.Ox 7.1 .
.Sh BUGS
An
.Fn ASIdOrRanges_new
function that installs the correct comparison function
on the stack of
.Vt ASIdOrRange
should have been part of the API to make it usable.
.Pp
.Fn ASIdentifierChoice_new
is of very limited use because
.Fn ASIdOrRanges_new
is missing.
.Pp
There is no way of ensuring that an
.Vt ASIdOrRanges
object is in canonical form unless it is part of an
.Vt ASIdentifiers
object.
It is therefore difficult to guarantee that the output of
.Fn i2d_ASIdentifierChoice
is conformant.
.Pp
RFC 3779 3.2.3.4 has
.Dq Fa asIdsOrRanges
while its type in this implementation is
.Vt ASIdOrRanges .

View file

@ -0,0 +1,516 @@
.\" $OpenBSD: IPAddressRange_new.3,v 1.4 2023/09/27 08:46:46 tb Exp $
.\"
.\" Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 27 2023 $
.Dt IPADDRESSRANGE_NEW 3
.Os
.Sh NAME
.Nm IPAddressRange_new ,
.Nm IPAddressRange_free ,
.Nm d2i_IPAddressRange ,
.Nm i2d_IPAddressRange ,
.Nm IPAddressOrRange_new ,
.Nm IPAddressOrRange_free ,
.Nm d2i_IPAddressOrRange ,
.Nm i2d_IPAddressOrRange ,
.Nm IPAddressChoice_new ,
.Nm IPAddressChoice_free ,
.Nm d2i_IPAddressChoice ,
.Nm i2d_IPAddressChoice ,
.Nm IPAddressFamily_new ,
.Nm IPAddressFamily_free ,
.Nm d2i_IPAddressFamily ,
.Nm i2d_IPAddressFamily
.Nd RFC 3779 IP address prefixes and ranges
.Sh SYNOPSIS
.In openssl/x509v3.h
.Ft "IPAddressRange *"
.Fn IPAddressRange_new void
.Ft void
.Fn IPAddressRange_free "IPAddressRange *range"
.Ft IPAddressRange *
.Fo d2i_IPAddressRange
.Fa "IPAddressRange **range"
.Fa "const unsigned char **der_in"
.Fa "long length"
.Fc
.Ft int
.Fo i2d_IPAddressRange
.Fa "IPAddressRange *range"
.Fa "unsigned char **der_out"
.Fc
.Ft "IPAddressOrRange *"
.Fn IPAddressOrRange_new void
.Ft void
.Fn IPAddressOrRange_free "IPAddressOrRange *aor"
.Ft IPAddressOrRange *
.Fo d2i_IPAddressOrRange
.Fa "IPAddressOrRange **aor"
.Fa "const unsigned char **der_in"
.Fa "long length"
.Fc
.Ft int
.Fo i2d_IPAddressOrRange
.Fa "IPAddressOrRange *aor"
.Fa "unsigned char **der_out"
.Fc
.Ft "IPAddressChoice *"
.Fn IPAddressChoice_new void
.Ft void
.Fn IPAddressChoice_free "IPAddressChoice *ac"
.Ft IPAddressChoice *
.Fo d2i_IPAddressChoice
.Fa "IPAddressChoice **ac"
.Fa "const unsigned char **der_in"
.Fa "long length"
.Fc
.Ft int
.Fo i2d_IPAddressChoice
.Fa "IPAddressChoice *ac"
.Fa "unsigned char **der_out"
.Fc
.Ft "IPAddressFamily *"
.Fn IPAddressFamily_new void
.Ft void
.Fn IPAddressFamily_free "IPAddressFamily *af"
.Ft IPAddressFamily *
.Fo d2i_IPAddressFamily
.Fa "IPAddressFamily **af"
.Fa "const unsigned char **der_in"
.Fa "long length"
.Fc
.Ft int
.Fo i2d_IPAddressFamily
.Fa "IPAddressFamily *af"
.Fa "unsigned char **der_out"
.Fc
.Sh DESCRIPTION
.Vt IPAddressRange ,
.Vt IPAddressOrRange ,
.Vt IPAddressChoice ,
and
.Vt IPAddressFamily
are building blocks of the RFC 3779
.Vt IPAddrBlocks
type representing the IP address delegation extension.
.Pp
Per RFC 3779, section 2.1.1,
an IPv4 or an IPv6 address is encoded in network byte order in an
ASN.1 BIT STRING of bit size 32 or 128 bits, respectively.
The bit size of a prefix is its prefix length.
In other words, all insignificant zero bits are omitted
from the encoding.
An address range is expressed as a pair of BIT STRINGs
where all least significant zero bits of the lower bound
and the all least significant one bits of the upper bound are omitted.
.Pp
The library provides no API for directly converting an IP address or
prefix (in any form) to and from an
.Vt ASN1_BIT_STRING .
It also provides no API for directly handling ranges.
The
.Vt ASN1_BIT_STRING
internals are subtle and directly manipulating them in the
context of the RFC 3779 API is discouraged.
The bit size of an
.Vt ASN1_BIT_STRING
representing an IP address prefix or range is eight times its length
member minus the lowest three bits of its flags, provided the
.Dv ASN1_STRING_FLAG_BITS_LEFT
flag is set.
.Pp
The
.Vt IPAddressRange
type defined in RFC 3779 section 2.2.3.9 is implemented as
.Bd -literal -offset indent
typedef struct IPAddressRange_st {
ASN1_BIT_STRING *min;
ASN1_BIT_STRING *max;
} IPAddressRange;
.Ed
.Pp
It represents the closed range [min,max] of IP addresses between
.Fa min
and
.Fa max ,
where
.Fa min
should be strictly smaller than
.Fa max
and the range should not be expressible as a prefix.
.Pp
.Fn IPAddressRange_new
allocates a new
.Vt IPAddressRange
object with allocated, empty
.Fa min
and
.Fa max ,
thus representing the entire address space.
.Pp
.Fn IPAddressRange_free
frees
.Fa range
including any data contained in it.
If
.Fa range
is
.Dv NULL ,
no action occurs.
.Pp
There is no dedicated type representing the
.Vt IPAddress
type defined in RFC 3779 section 2.2.3.8.
The API uses
.Vt ASN1_BIT_STRING
for this.
.Pp
The
.Vt IpAddressOrRange
type defined in RFC 3779 section 2.2.3.7 is implemented as
.Bd -literal -offset indent
typedef struct IPAddressOrRange_st {
int type;
union {
ASN1_BIT_STRING *addressPrefix;
IPAddressRange *addressRange;
} u;
} IPAddressOrRange;
.Ed
.Pp
representing an individual address prefix or an address range.
The
.Fa type
member should be set to
.Dv IPAddressOrRange_addressPrefix
or
.Dv IPAddressOrRange_addressRange
to indicate which member of the union
.Fa u
is valid.
.Pp
.Fn IPAddressOrRange_new
returns a new
.Vt IPAddressOrRange
object with invalid type and
.Dv NULL
members of the union
.Fa u .
.Pp
.Fn IPAddressOrRange_free
frees
.Fa aor
including any data contained in it,
provided
.Fa type
is set correctly.
If
.Fa aor
is
.Dv NULL ,
no action occurs.
.Pp
In order to express a list of address prefixes and address ranges,
RFC 3779 section 2.2.3.6
uses an ASN.1 SEQUENCE,
which is implemented via a
.Xr STACK_OF 3
construction over
.Vt IPAddressOrRange :
.Bd -literal -offset indent
typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges;
.Ed
.Pp
Since an
.Vt IPAddressOrRanges
object should be sorted in a specific way (see
.Xr X509v3_addr_canonize 3 Ns ),
a comparison function is needed for a correct instantiation
with
.Xr sk_new 3 .
The
.Fn v4IPAddressOrRange_cmp
and
.Fn v6IPAddressOrRange_cmp
functions are not directly exposed and not easily accessible
from outside the library,
and they are non-trivial to implement.
It is therefore discouraged to use
.Vt IPAddressOrRanges
objects that are not part of an
.Vt IPAddrBlocks
object.
.Pp
The
.Dq inherit
marker from RFC 3779 section 2.2.3.5 is implemented as
.Vt ASN1_NULL .
It has no dedicated type or API and can be instantiated with
.Xr ASN1_NULL_new 3 .
.Pp
The
.Vt IPAddressChoice
type defined in RFC 3779 section 2.2.3.4 is implemented as
.Bd -literal -offset indent
typedef struct IPAddressChoice_st {
int type;
union {
ASN1_NULL *inherit;
IPAddressOrRanges *addressesOrRanges;
} u;
} IPAddressChoice;
.Ed
.Pp
where the
.Fa type
member should be set to
.Dv IPAddressChoice_inherit
or
.Dv IPAddressChoice_addressesOrRanges
to indicate whether a given
.Vt IPAddressChoice
object represents an inherited list or an explicit list.
.Pp
.Fn IPAddressChoice_new
returns a new
.Vt IPAddressChoice
object with invalid type and
.Dv NULL
members of the union
.Fa u .
.Pp
.Fn IPAddressChoice_free
frees
.Fa ac
including any data contained in it,
provided
.Fa type
is set correctly.
.Pp
The
.Fa addressFamily
element defined in RFC 3779 section 2.2.3.3 is implemented as an
.Vt ASN1_OCTET_STRING
and it contains two or three octets.
The first two octets are always present and represent the
address family identifier (AFI)
in network byte order.
The optional subsequent address family identifier (SAFI)
occupies the third octet.
For IPv4 and IPv6,
.Dv IANA_AFI_IPV4
and
.Dv IANA_AFI_IPV6
are predefined.
Other AFIs are not supported by this implementation.
.Pp
The
.Vt IPAddressFamily
type defined in RFC 3779 section 2.2.3.2 is implemented as
.Bd -literal -offset indent
typedef struct IPAddressFamily_st {
ASN1_OCTET_STRING *addressFamily;
IPAddressChoice *ipAddressChoice;
} IPAddressFamily;
.Ed
.Pp
The
.Fa addressFamily
member indicates the address family the
.Fa ipAddressChoice
represents.
.Pp
.Fn IPAddressFamily_new
returns a new
.Vt IPAddressFamily
object with empty
.Fa addressFamily
and invalid
.Fa ipAddressChoice
members.
.Pp
.Fn IPAddressFamily_free
frees
.Fa af
including any data contained in it.
If
.Fa af
is
.Dv NULL ,
no action occurs.
.Pp
The
.Vt IPAddrBlocks
type defined in RFC 3779 section 2.2.3.1
uses an ASN.1 SEQUENCE,
which is implemented via a
.Xr STACK_OF 3
construction over
.Vt IPAddressFamily :
.Bd -literal -offset indent
typedef STACK_OF(IPAddressFamily) IPAddrBlocks;
.Ed
.Pp
It can be instantiated with
.Fn sk_IPAddressFamily_new_null
and the correct sorting function can be installed with
.Xr X509v3_addr_canonize 3 .
To populate it, use
.Xr X509v3_addr_add_prefix 3
and related functions.
.Pp
.Fn d2i_IPAddressRange ,
.Fn i2d_IPAddressRange ,
.Fn d2i_IPAddressOrRange ,
.Fn i2d_IPAddressOrRange ,
.Fn d2i_IPAddressChoice ,
.Fn i2d_IPAddressChoice ,
.Fn d2i_IPAddressFamily ,
and
.Fn i2d_IPAddressFamily ,
decode and encode ASN.1
.Vt IPAddressRange ,
.Vt IPAddressOrRange ,
.Vt IPAddressChoice ,
and
.Vt IPAddressFamily
objects.
For details about the semantics, examples, caveats, and bugs, see
.Xr ASN1_item_d2i 3 .
There is no easy way of ensuring that the encodings generated by
these functions are correct, unless they are applied to objects
that are part of a canonical
.Vt IPAddrBlocks
structure, see
.Xr X509v3_addr_is_canonical 3 .
.Sh RETURN VALUES
.Fn IPAddressRange_new
returns a new
.Vt IPAddressRange
object with allocated, empty members, or
.Dv NULL
if an error occurs.
.Pp
.Fn IPAddressOrRange_new
returns a new, empty
.Vt IPAddressOrRange
object or
.Dv NULL
if an error occurs.
.Pp
.Fn IPAddressChoice_new
returns a new, empty
.Vt IPAddressChoice
object or
.Dv NULL
if an error occurs.
.Pp
.Fn IPAddressFamily_new
returns a new
.Vt IPAddressFamily
object with allocated, empty members, or
.Dv NULL
if an error occurs.
.Pp
The encoding functions
.Fn d2i_IPAddressRange ,
.Fn d2i_IPAddressOrRange ,
.Fn d2i_IPAddressChoice ,
and
.Fn d2i_IPAddressFamily ,
return an
.Vt IPAddressRange ,
an
.Vt IPAddressOrRange ,
an
.Vt IPAddressChoice ,
or an
.Vt IPAddressFamily
object, respectively,
or
.Dv NULL
if an error occurs.
.Pp
The encoding functions
.Fn i2d_IPAddressRange ,
.Fn i2d_IPAddressOrRange ,
.Fn i2d_IPAddressChoice ,
and
.Fn i2d_IPAddressFamily ,
return the number of bytes successfully encoded
or a value <= 0 if an error occurs.
.Sh SEE ALSO
.Xr ASIdentifiers_new 3 ,
.Xr ASN1_BIT_STRING_new 3 ,
.Xr ASN1_OCTET_STRING_new 3 ,
.Xr ASN1_OCTET_STRING_set 3 ,
.Xr crypto 3 ,
.Xr X509_new 3 ,
.Xr X509v3_addr_add_inherit 3 ,
.Xr X509v3_addr_inherits 3
.Sh STANDARDS
RFC 3779: X.509 Extensions for IP Addresses and AS Identifiers:
.Bl -dash -compact
.It
section 2.2.3: Syntax
.It
section 2.2.3.1: Type IPAddrBlocks
.It
section 2.2.3.2: Type IPAddressFamily
.It
section 2.2.3.3: Element addressFamily
.It
section 2.2.3.4: Element ipAddressChoice and Type IPAddressChoice
.It
section 2.2.3.5: Element inherit
.It
section 2.2.3.6: Element addressesOrRanges
.It
section 2.2.3.7: Type IPAddressOrRange
.It
section 2.2.3.8: Element addressPrefix and Type IPAddress
.It
section 2.2.3.9: Elements addressRange and Type IPAddressRange
.El
.Pp
ITU-T Recommendation X.690, also known as ISO/IEC 8825-1:
Information technology - ASN.1 encoding rules:
Specification of Basic Encoding Rules (BER), Canonical Encoding
Rules (CER) and Distinguished Encoding Rules (DER),
section 8.6: Encoding of a bitstring value
.Sh HISTORY
These functions first appeared in OpenSSL 0.9.8e
and have been available since
.Ox 7.1 .
.Sh BUGS
.\" The internals do not seem to consistently apply and check
.\" .Dv ASN1_STRING_FLAG_BITS_LEFT
.\" which may lead to incorrect encoding and misinterpretation
As it stands, the API is barely usable
due to missing convenience accessors, constructors and destructors
and due to the complete absence of API that checks that the
individual building blocks are correct.
Extracting information from a given object can be done relatively
safely.
However, constructing objects is very error prone, be it
by hand or using the bug-ridden
.Xr X509v3_addr_add_inherit 3
API.
.Pp
RFC 3779 has element
.Dq addressesOrRanges .
Its type in this API is
.Vt IPAddressOrRanges .

View file

@ -1,10 +1,11 @@
# $OpenBSD: Makefile,v 1.268 2023/09/09 14:39:09 schwarze Exp $
# $OpenBSD: Makefile,v 1.274 2023/09/26 20:42:45 tb Exp $
.include <bsd.own.mk>
MAN= \
ACCESS_DESCRIPTION_new.3 \
AES_encrypt.3 \
ASIdentifiers_new.3 \
ASN1_BIT_STRING_set.3 \
ASN1_INTEGER_get.3 \
ASN1_NULL_new.3 \
@ -29,6 +30,7 @@ MAN= \
ASN1_parse_dump.3 \
ASN1_put_object.3 \
ASN1_time_parse.3 \
ASRange_new.3 \
AUTHORITY_KEYID_new.3 \
BASIC_CONSTRAINTS_new.3 \
BF_set_key.3 \
@ -220,6 +222,7 @@ MAN= \
EXTENDED_KEY_USAGE_new.3 \
GENERAL_NAME_new.3 \
HMAC.3 \
IPAddressRange_new.3 \
MD5.3 \
NAME_CONSTRAINTS_new.3 \
OBJ_NAME_add.3 \
@ -389,6 +392,11 @@ MAN= \
X509_verify_cert.3 \
X509at_add1_attr.3 \
X509at_get_attr.3 \
X509v3_addr_add_inherit.3 \
X509v3_addr_get_range.3 \
X509v3_addr_inherits.3 \
X509v3_asid_add_id_or_range.3 \
X509v3_asid_add_id_or_range.3 \
X509v3_get_ext_by_NID.3 \
a2d_ASN1_OBJECT.3 \
crypto.3 \
@ -431,8 +439,8 @@ MAN= \
i2d_PKCS7_bio_stream.3 \
lh_new.3 \
lh_stats.3 \
s2i_ASN1_INTEGER.3 \
openssl.cnf.5 \
s2i_ASN1_INTEGER.3 \
x509v3.cnf.5
all clean cleandir depend includes obj tags:

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: X509V3_get_d2i.3,v 1.20 2023/02/23 18:12:32 job Exp $
.\" $OpenBSD: X509V3_get_d2i.3,v 1.21 2023/09/25 07:47:52 tb Exp $
.\" full merge up to: OpenSSL ff7fbfd5 Nov 2 11:52:01 2015 +0000
.\" selective merge up to: OpenSSL 99d63d46 Oct 26 13:56:48 2016 -0400
.\"
@ -49,7 +49,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: February 23 2023 $
.Dd $Mdocdate: September 25 2023 $
.Dt X509V3_GET_D2I 3
.Os
.Sh NAME
@ -339,6 +339,9 @@ as RFC 5280.
.It Policy Mappings Ta Dv NID_policy_mappings
.It Policy Constraints Ta Dv NID_policy_constraints
.It Inhibit Any Policy Ta Dv NID_inhibit_any_policy
.It IP Address Delegation Ta Dv NID_sbgp_ipAddrBlock
.It Autonomous System Identifier Delegation\
Ta Dv NID_sbgp_autonomousSysNum
.El
.Ss Netscape Certificate Extensions
The following are (largely obsolete) Netscape certificate extensions.

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: X509_new.3,v 1.37 2023/04/30 14:49:47 tb Exp $
.\" $OpenBSD: X509_new.3,v 1.41 2023/09/26 20:42:45 tb Exp $
.\" full merge up to: OpenSSL 99d63d46 Oct 26 13:56:48 2016 -0400
.\"
.\" This file is a derived work.
@ -66,7 +66,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: April 30 2023 $
.Dd $Mdocdate: September 26 2023 $
.Dt X509_NEW 3
.Os
.Sh NAME
@ -193,10 +193,13 @@ or
.Dv NULL
if an error occurs.
.Sh SEE ALSO
.Xr ASIdentifiers_new 3 ,
.Xr ASRange_new 3 ,
.Xr AUTHORITY_KEYID_new 3 ,
.Xr BASIC_CONSTRAINTS_new 3 ,
.Xr crypto 3 ,
.Xr d2i_X509 3 ,
.Xr IPAddressRange_new 3 ,
.Xr PKCS8_PRIV_KEY_INFO_new 3 ,
.Xr X509_ALGOR_new 3 ,
.Xr X509_ATTRIBUTE_new 3 ,
@ -238,7 +241,11 @@ if an error occurs.
.Xr X509_STORE_CTX_new 3 ,
.Xr X509_STORE_get_by_subject 3 ,
.Xr X509_STORE_new 3 ,
.Xr X509_TRUST_set 3
.Xr X509_TRUST_set 3 ,
.Xr X509v3_addr_add_inherit 3 ,
.Xr X509v3_addr_get_range 3 ,
.Xr X509v3_addr_inherits 3 ,
.Xr X509v3_asid_add_id_or_range 3
.Sh STANDARDS
RFC 5280: Internet X.509 Public Key Infrastructure Certificate and
Certificate Revocation List (CRL) Profile

View file

@ -0,0 +1,472 @@
.\" $OpenBSD: X509v3_addr_add_inherit.3,v 1.5 2023/09/27 08:46:46 tb Exp $
.\"
.\" Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 27 2023 $
.Dt X509V3_ADDR_ADD_INHERIT 3
.Os
.Sh NAME
.Nm X509v3_addr_add_inherit ,
.Nm X509v3_addr_add_prefix ,
.Nm X509v3_addr_add_range ,
.Nm X509v3_addr_canonize ,
.Nm X509v3_addr_is_canonical
.Nd RFC 3779 IP address delegation extensions
.Sh SYNOPSIS
.In openssl/x509v3.h
.Ft int
.Fo X509v3_addr_add_inherit
.Fa "IPAddrBlocks *addrblocks"
.Fa "const unsigned afi"
.Fa "const unsigned *safi"
.Fc
.Ft int
.Fo X509v3_addr_add_prefix
.Fa "IPAddrBlocks *addrblocks"
.Fa "const unsigned afi"
.Fa "const unsigned *safi"
.Fa "unsigned char *prefix"
.Fa "const int prefixlen"
.Fc
.Ft int
.Fo X509v3_addr_add_range
.Fa "IPAddrBlocks *addrblocks"
.Fa "const unsigned afi"
.Fa "const unsigned *safi"
.Fa "unsigned char *min"
.Fa "unsigned char *max"
.Fc
.Ft int
.Fo X509v3_addr_canonize
.Fa "IPAddrBlocks *addrblocks"
.Fc
.Ft int
.Fo X509v3_addr_is_canonical
.Fa "IPAddrBlocks *addrblocks"
.Fc
.Sh DESCRIPTION
An
.Vt IPAddrBlocks
object represents the content of
an X509v3 IP address blocks delegation extension
as defined in RFC 3779, section 2.2.3.1.
It holds lists of IP address prefixes and IP address ranges
delegated from the issuer to the subject of the certificate.
It can be instantiated as explained in the EXAMPLES section
and its internals are documented in
.Xr IPAddressRange_new 3 .
.Pp
Each list in a well-formed
.Vt IPAddrBlocks
object is uniquely identified by
an address family identifier (AFI) and
an optional subsequent address family identifier (SAFI).
Lists can be absent or can contain an
.Dq inherit
marker to indicate that the resources are to be inherited
from the corresponding list of the issuer certificate.
.Pp
Per specification, an AFI is an unsigned 16-bit integer and
a SAFI is an unsigned 8-bit integer.
For IPv4 and IPv6 there are the predefined constants
.Dv IANA_AFI_IPV4
and
.Dv IANA_AFI_IPV6 ,
which should be the only values used for
.Fa afi
in this API.
In practice,
.Fa safi
is always NULL.
.Fa afi
is generally silently truncated to its lowest 16 bits and, if
.Fa safi
is non-NULL,
only the lowest 8 bits of the value pointed at are used.
.Pp
.Fn X509v3_addr_add_inherit
adds a list with an
.Dq inherit
marker to
.Fa addrblocks .
If a list corresponding to
.Fa afi
and
.Fa safi
already exists, no action occurs if it is marked
.Dq inherit ,
otherwise the call fails.
.Pp
.Fn X509v3_addr_add_prefix
adds a newly allocated internal representation of the
.Fa prefix
of length
.Fa prefixlen
to the list corresponding to
.Fa afi
and the optional
.Fa safi
in
.Fa addrblocks .
If no such list exists, it is created first.
If the list exists and is marked
.Dq inherit ,
the call fails.
.Fa prefix
is expected to be a byte array in network byte order.
It should point at enough memory to accommodate
.Fa prefixlen
bits and it is recommended that all the bits not covered by
the prefixlen be set to 0.
It is the caller's responsibility to ensure that the prefix
has no address in common with any of
the prefixes or ranges already in the list.
If
.Fa afi
is
.Dv IANA_AFI_IPV4 ,
.Fa prefixlen
should be between 0 and 32 (inclusive) and if
.Fa afi
is
.Dv IANA_AFI_IPV6 ,
.Fa prefixlen
should be between 0 and 128 (inclusive).
.Pp
.Fn X509v3_addr_add_range
is similar to
.Fn X509v3_addr_add_prefix
for the closed interval of IP addresses between
.Fa min
and
.Fa max
in network presentation.
If
.Fa afi
is
.Dv IANA_AFI_IPV4 ,
.Fa min
and
.Fa max
should point at 4 bytes of memory
and if
.Fa afi
is
.Dv IANA_AFI_IPV6 ,
.Fa min
and
.Fa max
should point at 16 bytes of memory.
In case the range of IP addresses between
.Fa min
and
.Fa max
is a prefix, a prefix will be added instead of a range.
It is the caller's responsibility to ensure that
.Fa min
is less than or equal to
.Fa max
and that it does not contain any address already present
in the list.
Failure to do so will result in a subsequent failure of
.Fn X509v3_addr_canonize .
.Pp
.Fn X509v3_addr_canonize
attempts to bring the
.Pf non- Dv NULL
.Fa addrblocks
into canonical form.
An
.Vt IPAddrBlocks
object is said to be in canonical form if it conforms
to the ordering specified in RFC 3779:
section 2.2.3.3 requires that
the list of lists be sorted first by increasing
.Fa afi
and then by increasing
.Fa safi ,
where NULL is the minimal SAFI;
section 2.2.3.6 requires that each list be in minimal form and sorted.
The minimality requirement is that all adjacent prefixes
and ranges must be merged into a single range and that each
range must be expressed as a prefix, if possible.
In particular, any given address can be in at most one list entry.
The order is by increasing minimal IP address in network byte order.
.Pp
.Fn X509v3_addr_is_canonical
indicates whether
.Fa addrblocks
is in canonical form.
.Sh RETURN VALUES
All these functions return 1 on success and 0 on failure.
Memory allocation failure is one possible reason for all of them.
Sometimes an error code can be obtained by
.Xr ERR_get_error 3 .
.Pp
.Fn X509v3_addr_add_inherit
fails if the list corresponding to
.Fa afi
and the optional
.Fa safi
already exists and is not marked
.Dq inherit .
.Pp
.Fn X509v3_addr_add_prefix
and
.Fn X509v3_addr_add_range
fail if a list corresponding to
.Fa afi
and the optional
.Fa safi
already exists and is marked
.Dq inherit ,
or if
.Fa prefixlen
is outside the interval [0,32] for IPv4 addresses
or [0,128] for IPv6 addresses.
.Pp
.Fn X509v3_addr_canonize
fails if one of the lists in
.Fa addrblocks
is malformed,
in particular if it contains corrupt, overlapping,
or duplicate entries.
Corruption includes ranges where
.Fa max
is strictly smaller than
.Fa min .
The error conditions are generally indistinguishable.
.Pp
.Fn X509v3_addr_is_canonical
returns 1 if
.Fa addrblocks
is in canonical form.
A return value of 0 can indicate non-canonical form or a corrupted list.
.Sh EXAMPLES
Construct the first extension from RFC 3779, Appendix B.
.Bd -literal
#include <sys/socket.h>
#include <arpa/inet.h>
#include <err.h>
#include <stdio.h>
#include <unistd.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
const char *prefixes[6] = {
"10.0.32/20", "10.0.64/24", "10.1/16",
"10.2.48/20", "10.2.64/24", "10.3/16",
};
#define N_PREFIXES (sizeof(prefixes) / sizeof(prefixes[0]))
static void
hexdump(const unsigned char *buf, size_t len)
{
size_t i;
for (i = 1; i <= len; i++)
printf(" 0x%02x,%s", buf[i - 1], i % 8 ? "" : "\en");
if (len % 8)
printf("\en");
}
int
main(void)
{
IPAddrBlocks *addrblocks;
X509_EXTENSION *ext;
unsigned char *der;
int der_len;
size_t i;
if (pledge("stdio", NULL) == -1)
err(1, "pledge");
/*
* Somebody forgot to implement IPAddrBlocks_new(). IPAddrBlocks
* is the same as STACK_OF(IPAddressFamily). As such, it should
* have IPAddressFamily_cmp() as its comparison function. It is
* not possible to call sk_new(3) because IPAddressFamily_cmp()
* is not part of the public API. The correct comparison function
* can be installed as a side-effect of X509v3_addr_canonize(3).
*/
if ((addrblocks = sk_IPAddressFamily_new_null()) == NULL)
err(1, "sk_IPAddressFamily_new_null");
if (!X509v3_addr_canonize(addrblocks))
errx(1, "X509v3_addr_canonize");
/* Add the prefixes as IPv4 unicast. */
for (i = 0; i < N_PREFIXES; i++) {
unsigned char addr[16] = {0};
int len;
int unicast = 1; /* SAFI for unicast forwarding. */
len = inet_net_pton(AF_INET, prefixes[i], addr,
sizeof(addr));
if (len == -1)
errx(1, "inet_net_pton(%s)", prefixes[i]);
if (!X509v3_addr_add_prefix(addrblocks, IANA_AFI_IPV4,
&unicast, addr, len))
errx(1, "X509v3_addr_add_prefix(%s)", prefixes[i]);
}
if (!X509v3_addr_add_inherit(addrblocks, IANA_AFI_IPV6, NULL))
errx(1, "X509v3_addr_add_inherit");
/*
* Ensure the extension is in canonical form. Otherwise the two
* adjacent prefixes 10.2.48/20 and 10.2.64/24 are not merged into
* the range 10.2.48.0--10.2.64.255. This results in invalid DER
* encoding from X509V3_EXT_i2d(3) and i2d_X509_EXTENSION(3).
*/
if (!X509v3_addr_canonize(addrblocks))
errx(1, "X509v3_addr_canonize");
/* Create the extension. The 1 indicates that it is critical. */
ext = X509V3_EXT_i2d(NID_sbgp_ipAddrBlock, 1, addrblocks);
if (ext == NULL)
errx(1, "X509V3_EXT_i2d");
der = NULL;
if ((der_len = i2d_X509_EXTENSION(ext, &der)) <= 0)
errx(1, "i2d_X509_EXTENSION");
hexdump(der, der_len);
/* One way of implementing IPAddrBlocks_free(). */
sk_IPAddressFamily_pop_free(addrblocks, IPAddressFamily_free);
X509_EXTENSION_free(ext);
free(der);
return 0;
}
.Ed
.Pp
Implement the missing public API
.Fn d2i_IPAddrBlocks
and
.Fn i2d_IPAddrBlocks
using
.Xr ASN1_item_d2i 3 :
.Bd -literal
IPAddrBlocks *
d2i_IPAddrBlocks(IPAddrBlocks **addrblocks, const unsigned char **in,
long len)
{
const X509V3_EXT_METHOD *v3_addr;
if ((v3_addr = X509V3_EXT_get_nid(NID_sbgp_ipAddrBlock)) == NULL)
return NULL;
return (IPAddrBlocks *)ASN1_item_d2i((ASN1_VALUE **)addrblocks,
in, len, ASN1_ITEM_ptr(v3_addr->it));
}
int
i2d_IPAddrBlocks(IPAddrBlocks *addrblocks, unsigned char **out)
{
const X509V3_EXT_METHOD *v3_addr;
if ((v3_addr = X509V3_EXT_get_nid(NID_sbgp_ipAddrBlock)) == NULL)
return -1;
return ASN1_item_i2d((ASN1_VALUE *)addrblocks, out,
ASN1_ITEM_ptr(v3_addr->it));
}
.Ed
.Pp
The use of the undocumented macro
.Dv ASN1_ITEM_ptr()
is necessary if compatibility with modern versions of other implementations
is desired.
.Sh SEE ALSO
.Xr ASIdentifiers_new 3 ,
.Xr crypto 3 ,
.Xr inet_net_ntop 3 ,
.Xr inet_ntop 3 ,
.Xr IPAddressRange_new 3 ,
.Xr X509_new 3 ,
.Xr X509v3_asid_add_id_or_range 3 ,
.Xr X509v3_addr_get_range 3
.Sh STANDARDS
RFC 3779: X.509 Extensions for IP Addresses and AS Identifiers:
.Bl -dash -compact
.It
section 2: IP Address delegation extension
.El
.Pp
RFC 7020: The Internet Numbers Registry System
.Pp
RFC 7249: Internet Number Registries
.Pp
.Rs
.%T Address Family Numbers
.%U https://www.iana.org/assignments/address-family-numbers
.Re
.Pp
.Rs
.%T Subsequent Address Family Identifiers (SAFI) Parameters
.%U https://www.iana.org/assignments/safi-namespace
.Re
.Sh HISTORY
These functions first appeared in OpenSSL 0.9.8e
and have been available since
.Ox 7.1 .
.Sh BUGS
.Fn IPAddrBlocks_new ,
.Fn IPAddrBlocks_free ,
.Fn d2i_IPAddrBlocks ,
and
.Fn i2d_IPAddrBlocks
do not exist and
.Fa IPAddrBlocks_it
is not public.
The above examples show how to implement the four missing functions
with public API.
.Pp
.Fn X509v3_addr_add_range
should check for inverted range bounds and overlaps
on insertion and fail instead of creating a nonsensical
.Fa addr
that fails to be canonized by
.Fn X509v3_addr_canonize .
.Pp
If
.Dv NULL
is passed to
.Xr X509v3_asid_canonize 3 ,
it succeeds.
.Fn X509v3_addr_is_canonical
considers
.Dv NULL
to be a canonical
.Vt IPAddrBlocks .
In contrast,
.Fn X509v3_addr_canonize
crashes with a
.Dv NULL
dereference.
.Pp
The code only supports the IPv4 and IPv6 AFIs.
This is not consistently enforced across implementations.
.Pp
.Fn X509v3_addr_add_range
fails to clear the unused bits set to 1 in the last octet of
the
.Vt ASN1_BIT_STRING
representation of
.Fa max .
This confuses some software.

View file

@ -0,0 +1,134 @@
.\" $OpenBSD: X509v3_addr_get_range.3,v 1.1 2023/09/26 18:35:34 tb Exp $
.\"
.\" Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 26 2023 $
.Dt X509V3_ADDR_GET_RANGE 3
.Os
.Sh NAME
.Nm X509v3_addr_get_afi ,
.Nm X509v3_addr_get_range
.Nd parse helpers for the IP address delegation extension
.Sh SYNOPSIS
.In openssl/x509v3.h
.Ft unsigned
.Fn X509v3_addr_get_afi "const IPAddressFamily *af"
.Ft int
.Fo X509v3_addr_get_range
.Fa "IPAddressOrRange *aor"
.Fa "const unsigned afi"
.Fa "unsigned char *min"
.Fa "unsigned char *max"
.Fa "const int length"
.Fc
.Sh DESCRIPTION
.Fn X509v3_addr_get_afi
returns the address family identifier (AFI) of
.Fa af .
.Pp
.Fn X509v3_addr_get_range
converts the minimum and maximum addresses in
the address prefix or range
.Fa aor
from internal encoding to IP addresses in network byte order
and places copies in the arrays
.Fa min
and
.Fa max ,
of size
.Fa length .
The
.Fa length
must be large enough to accommodate an address for
.Fa afi ,
which for
.Dv IANA_AFI_IPV4 ,
is at least 4,
and for
.Dv IANA_AFI_IPV6
at least 16.
.Sh RETURN VALUES
.Fn X509v3_addr_get_afi
returns the afi encoded in
.Fa af
or 0 if
.Fa af
does not contain a valid AFI, or if the AFI is not IPv4 or IPv6.
.Pp
.Fn X509v3_addr_get_range
returns the number of bytes copied into
.Fa min
and
.Fa max
or 0 on error.
An error occurs if
.Fa aor
is malformed, if
.Fa afi
is not
.Dv IANA_AFI_IPV4
or
.Dv IANA_AFI_IPV6 ,
if either
.Fa min
or
.Fa max
is
.Dv NULL ,
or if
.Fa length
is smaller than 4 or 16, respectively.
.Sh SEE ALSO
.Xr crypto 3 ,
.Xr inet_ntop 3 ,
.Xr IPAddressRange_new 3 ,
.Xr X509_new 3 ,
.Xr X509v3_addr_add_inherit 3
.Sh STANDARDS
RFC 3779: X.509 Extensions for IP Addresses and AS Identifiers:
.Bl -dash -compact
.It
section 2: IP Address delegation extension
.It
section 2.2.3.3: Element addressFamily
.It
section 2.2.3.7: Type IPAddressOrRange
.It
section 2.2.3.8: Element addressPrefix and Type IPAddress
.El
.Pp
.Rs
.%T Address Family Numbers
.%U https://www.iana.org/assignments/address-family-numbers
.Re
.Sh HISTORY
These functions first appeared in OpenSSL 0.9.8e
and have been available since
.Ox 7.1 .
.Sh BUGS
There is no accessor for the SAFI of
.Fa af .
.Pp
An error from
.Fn X509v3_addr_get_afi
is indistinguishable from the reserved AFI 0 being set on
.Fa af .
.Pp
It is not entirely clear how a caller is supposed to obtain an
.Vt IPAddressFamily
object or an
.Vt IPAddressOrRange
object without reaching into various structs documented in
.Xr IPAddressRange_new 3 .

View file

@ -0,0 +1,106 @@
.\" $OpenBSD: X509v3_addr_inherits.3,v 1.2 2023/09/27 08:46:46 tb Exp $
.\"
.\" Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 27 2023 $
.Dt X509V3_ADDR_INHERITS 3
.Os
.Sh NAME
.Nm X509v3_addr_inherits ,
.Nm X509v3_asid_inherits
.Nd RFC 3779 inheritance
.Sh SYNOPSIS
.In openssl/x509v3.h
.Ft int
.Fn X509v3_addr_inherits "IPAddrBlocks *addrblocks"
.Ft int
.Fn X509v3_asid_inherits "ASIdentifiers *asids"
.Sh DESCRIPTION
.Fn X509v3_addr_inherits
determines if there is at least one address family in
.Fa addrblocks
that uses inheritance.
.Pp
.Fn X509v3_asid_inherits
is intended to determine if at least one of
the list of autonomous system numbers or
the list of routing domain identifiers
uses inheritance.
.Sh RETURN VALUES
.Fn X509v3_addr_inherits
returns 1 if and only if
.Fa addrblocks
contains at least one
.Fa IPAddressFamily
object that is correctly marked
.Dq inherit :
its
.Fa IPAddressChoice
is of
.Fa type
.Dv IPAddressChoice_inherit
and its
.Fa inherit
element is present.
Otherwise it returns 0.
.Pp
.Fn X509v3_asid_inherits
returns 1 if and only if
at least one of the
.Fa asnum
or the
.Fa rdi
lists has
.Fa type
.Dv ASIdentifierChoice_inherit .
Otherwise
.Fn X509v3_asid_inherits 3
returns 0.
.Sh SEE ALSO
.Xr ASIdentifiers_new 3 ,
.Xr ASRange_new 3 ,
.Xr crypto 3 ,
.Xr IPAddressRange_new 3 ,
.Xr X509_new 3 ,
.Xr X509v3_addr_add_inherit 3 ,
.Xr X509v3_asid_add_inherit 3
.Sh STANDARDS
RFC 3779: X.509 Extensions for IP Addresses and AS Identifiers:
.Bl -dash -compact
.It
section 2: IP Address delegation extension
.It
section 2.2.3.5: Element inherit
.It
section 3: AS identifiers delegation extension
.It
section 3.2.3.3: Element inherit
.El
.Sh HISTORY
These functions first appeared in OpenSSL 0.9.8e
and have been available since
.Ox 7.1 .
.Sh BUGS
.Fn X509v3_asid_inherits
ignores whether the
.Fa inherit
element is present or absent in the list that is considered to use inheritance.
.Pp
There is no API that determines whether all lists contained in an
.Vt ASIdentifiers
or an
.Vt IPAddrBlocks
objects inherit.
See RFC 9287, 5.1.2 for an example where this is relevant.

View file

@ -0,0 +1,321 @@
.\" $OpenBSD: X509v3_asid_add_id_or_range.3,v 1.5 2023/09/27 08:46:46 tb Exp $
.\"
.\" Copyright (c) 2021-2023 Theo Buehler <tb@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 27 2023 $
.Dt X509V3_ASID_ADD_ID_OR_RANGE 3
.Os
.Sh NAME
.Nm X509v3_asid_add_id_or_range ,
.Nm X509v3_asid_add_inherit ,
.Nm X509v3_asid_canonize ,
.Nm X509v3_asid_is_canonical
.Nd RFC 3779 autonomous system identifier delegation extension
.Sh SYNOPSIS
.In openssl/x509v3.h
.Ft int
.Fo X509v3_asid_add_id_or_range
.Fa "ASIdentifiers *asid"
.Fa "int type"
.Fa "ASN1_INTEGER *min"
.Fa "ASN1_INTEGER *max"
.Fc
.Ft int
.Fo X509v3_asid_add_inherit
.Fa "ASIdentifiers *asid"
.Fa "int type"
.Fc
.Ft int
.Fo X509v3_asid_canonize
.Fa "ASIdentifiers *asid"
.Fc
.Ft int
.Fo X509v3_asid_is_canonical
.Fa "ASIdentifiers *asid"
.Fc
.Sh DESCRIPTION
An
.Vt ASIdentifiers
object represents the content of the X509v3 certificate extension
defined in RFC 3779, section 3.2.3.1.
It can be instantiated with
.Xr ASIdentifiers_new 3
and its internals are documented in
.Xr ASRange_new 3 .
.Pp
An autonomous system is identified by an unsigned 32-bit integer,
called an AS identifier or AS number.
An
.Vt ASIdentifiers
object can hold two lists:
a list of
.Fa type
.Dv V3_ASID_ASNUM
containing individual AS identifiers and ranges of AS identifiers,
and an obsolete list of
.Fa type
.Dv V3_ASID_RDI
containing routing domain identifiers (RDIs).
Either of these lists may be absent, or it may contain nothing
but a special
.Dq inherit
marker that indicates that the list is inherited from the issuer
of the certificate.
.Pp
.Fn X509v3_asid_add_id_or_range
adds an individual identifier or a range of identifiers to the list of
.Fa type
(either
.Dv V3_ASID_ASNUM
or
.Dv V3_ASID_RDI )
in
.Fa asid .
If no such list exists, it is created first.
If a list of
.Fa type
already exists and contains the
.Dq inherit
marker, the call fails.
.Fa min
must be a
.Pf non- Dv NULL
.Vt ASN1_INTEGER .
If
.Fa max
is
.Dv NULL ,
.Fa min
is added as an individual identifier.
Ownership of
.Fa min
and
.Fa max
is transferred to
.Fa asid
on success.
It is the responsibility of the caller to ensure that
the resulting
.Fa asid
does not contain lists with overlapping ranges and that
.Fa min
is strictly less than
.Fa max
if both are
.Pf non- Dv NULL .
The caller should also ensure that the AS identifiers are
32-bit integers.
Failure to do so may result in an
.Fa asid
that cannot be brought into canonical form by
.Fn X509v3_asid_canonize .
.Pp
.Fn X509v3_asid_add_inherit
adds the list of
.Fa type
(either
.Dv V3_ASID_ASNUM
or
.Dv V3_ASID_RDI )
in
.Fa asid
if necessary and marks it
.Dq inherit .
This fails if
.Fa asid
already contains a list of
.Fa type
that is not marked
.Dq inherit .
.Pp
.Fn X509v3_asid_canonize
attempts to bring both lists in
.Fa asid
into canonical form.
If
.Fa asid
is
.Dv NULL
the call succeeds and no action occurs.
A list is in canonical form if it is either one of
.Bl -dash -compact
.It
absent,
.It
marked
.Dq inherit ,
.It
non-empty and all identifiers and ranges are listed in increasing order.
Ranges must not overlap,
.\" the following is not currently specified and leads to ambiguity:
.\" contain at least two elements,
and adjacent ranges must be fully merged.
.El
.Fn X509v3_asid_canonize
merges adjacent ranges
but refuses to merge overlapping ranges or to discard duplicates.
For example, the adjacent ranges [a,b] and [b+1,c] are merged
into the single range [a,c], but if both [a,b] and [b,c] appear in a list,
this results in an error since they are considered overlapping.
Likewise, the identifier a is absorbed into the adjacent
range [a+1,b] to yield [a,b].
.Fn X509v3_asid_canonize
errors if the minimum of any range is larger than the maximum.
In contrast, minimum and maximum of a range may be equal.
.Pp
.Fn X509v3_asid_is_canonical
checks whether
.Fa asid
is in canonical form.
Once
.Fn X509v3_asid_canonize
is called successfully on
.Fa asid ,
all subsequent calls to
.Fn X509v3_asid_is_canonical
succeed on an unmodified
.Fa asid
unless memory allocation fails.
.Sh RETURN VALUES
All these functions return 1 on success and 0 on failure.
.Pp
.Fn X509v3_asid_add_id_or_range
and
.Fn X509v3_asid_add_inherit
fail if
.Fa asid
is
.Dv NULL
or if
.Fa type
is distinct from
.Dv V3_ASID_ASNUM
and
.Dv V3_ASID_RDI ,
or on memory allocation failure.
In addition,
.Fn X509v3_asid_add_id_or_range
fails if
.Fa asid
contains a list of
.Fa type
that is marked
.Dq inherit ,
and
.Fn X509v3_asid_add_inherit
fails if
.Fa asid
contains a list of
.Fa type
that is not marked
.Dq inherit .
.Pp
.Fn X509v3_asid_canonize
fails if either list is empty and not marked
.Dq inherit ,
or if it is malformed, or if memory allocation fails.
Malformed lists include lists containing duplicate, overlapping,
or malformed elements, for example AS ranges where the minimum is
larger than the maximum.
Some of these failure modes result in an error being pushed onto the
error stack.
.Pp
.Fn X509v3_asid_is_canonical
returns 1 if
.Fa asid
is canonical and 0 if it is not canonical or on memory allocation
failure.
.Sh SEE ALSO
.Xr ASIdentifiers_new 3 ,
.Xr crypto 3 ,
.Xr s2i_ASN1_INTEGER 3 ,
.Xr X509_new 3 ,
.Xr X509v3_addr_add_inherit 3
.Sh STANDARDS
RFC 3779: X.509 Extensions for IP Addresses and AS Identifiers,
.Bl -dash -compact
.It
section 3: Autonomous System Delegation Extension
.El
.Pp
.Rs
.%T Autonomous System (AS) Numbers
.%U https://www.iana.org/assignments/as-numbers
.Re
.Sh HISTORY
These functions first appeared in OpenSSL 0.9.8e
and have been available since
.Ox 7.1 .
.Sh BUGS
.Fn X509v3_asid_add_id_or_range
does not check for inverted range bounds and overlaps
on insertion.
It is very easy to create an
.Fa asid
that fails to be canonized by
.Fn X509v3_asid_canonize
and it is very hard to diagnose why.
.Pp
Both
.Fn X509v3_asid_add_id_or_range
and
.Fn X509v3_asid_add_inherit
can leave
.Fa asid
in a corrupted state if memory allocation fails during their execution.
In addition,
.Fn X509v3_asid_add_id_or_range
may already have freed the
.Fa min
and
.Fa max
arguments on failure.
.Pp
RFC 3779 does not explicitly disallow ranges where the minimum
is equal to the maximum.
The isolated AS identifier a and
the AS range [a,a] where the minimum and the maximum are equal to a
have the same semantics.
.Fn X509v3_asid_is_canonical
accepts both representations as valid and
.Fn X509v3_asid_canonize
does not prefer either representation over the other.
The encodings of the two representations produced by
.Xr i2d_ASIdentifiers 3
are distinct.
.Pp
.Fn X509v3_asid_is_canonical
does not fully check inheriting lists to be well formed.
It only checks the
.Fa type
to be
.Dv ASIdentifierChoice_inherit
and ignores the presence or absence of the
.Fa inherit
element.
.Fn X509v3_asid_canonize
does not fix that up.
This can lead to incorrect or unexpected DER encoding of
.Dq canonical
.Vt ASIdentifiers
objects.
In particular, it is possible to construct an
.Vt ASIdentifiers
object for which both
.Fn X509v3_asid_is_canonical
and
.Xr X509v3_asid_inherits 3
return 1, and after a round trip through DER the latter
returns 0.

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: d2i_ASN1_NULL.3,v 1.4 2021/11/22 16:19:54 schwarze Exp $
.\" $OpenBSD: d2i_ASN1_NULL.3,v 1.5 2023/09/26 09:36:22 tb Exp $
.\"
.\" Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
.\"
@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: November 22 2021 $
.Dd $Mdocdate: September 26 2023 $
.Dt D2I_ASN1_NULL 3
.Os
.Sh NAME
@ -83,7 +83,7 @@ ITU-T Recommendation X.690, also known as ISO/IEC 8825-1:
Information technology - ASN.1 encoding rules:
Specification of Basic Encoding Rules (BER), Canonical Encoding
Rules (CER) and Distinguished Encoding Rules (DER),
section 8.8: Encoding of null value
section 8.8: Encoding of a null value
.Sh HISTORY
.Fn d2i_ASN1_NULL
and

View file

@ -1,4 +1,4 @@
/* $OpenBSD: x509_addr.c,v 1.89 2023/09/11 00:50:47 job Exp $ */
/* $OpenBSD: x509_addr.c,v 1.90 2023/09/27 11:29:22 tb Exp $ */
/*
* Contributed to the OpenSSL Project by the American Registry for
* Internet Numbers ("ARIN").
@ -388,14 +388,17 @@ IPAddressFamily_set_inheritance(IPAddressFamily *af)
* What's the address length associated with this AFI?
*/
static int
length_from_afi(const unsigned afi)
length_from_afi(const unsigned afi, int *length)
{
switch (afi) {
case IANA_AFI_IPV4:
return 4;
*length = 4;
return 1;
case IANA_AFI_IPV6:
return 16;
*length = 16;
return 1;
default:
*length = 0;
return 0;
}
}
@ -425,6 +428,9 @@ IPAddressFamily_afi_safi(const IPAddressFamily *af, uint16_t *out_afi,
if (!CBS_get_u16(&cbs, &afi))
return 0;
if (afi != IANA_AFI_IPV4 && afi != IANA_AFI_IPV6)
return 0;
/* Fetch the optional SAFI. */
if (CBS_len(&cbs) != 0) {
if (!CBS_get_u8(&cbs, &safi))
@ -471,9 +477,7 @@ IPAddressFamily_afi_length(const IPAddressFamily *af, int *out_length)
if (!IPAddressFamily_afi(af, &afi))
return 0;
*out_length = length_from_afi(afi);
return 1;
return length_from_afi(afi, out_length);
}
#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
@ -879,16 +883,15 @@ make_addressPrefix(IPAddressOrRange **out_aor, uint8_t *addr, uint32_t afi,
int prefix_len)
{
IPAddressOrRange *aor = NULL;
int afi_len, max_len, num_bits, num_octets;
int afi_len, num_bits, num_octets;
uint8_t unused_bits;
if (prefix_len < 0)
goto err;
max_len = 16;
if ((afi_len = length_from_afi(afi)) > 0)
max_len = afi_len;
if (prefix_len > 8 * max_len)
if (!length_from_afi(afi, &afi_len))
goto err;
if (prefix_len > 8 * afi_len)
goto err;
num_octets = (prefix_len + 7) / 8;
@ -1062,11 +1065,14 @@ make_IPAddressFamily(IPAddrBlocks *addr, const unsigned afi,
if (!CBB_init(&cbb, 0))
goto err;
/* XXX - should afi <= 65535 and *safi <= 255 be checked here? */
if (afi != IANA_AFI_IPV4 && afi != IANA_AFI_IPV6)
goto err;
if (!CBB_add_u16(&cbb, afi))
goto err;
if (safi != NULL) {
if (*safi > 255)
goto err;
if (!CBB_add_u8(&cbb, *safi))
goto err;
}
@ -1197,7 +1203,8 @@ X509v3_addr_add_range(IPAddrBlocks *addr, const unsigned afi,
if ((aors = make_prefix_or_range(addr, afi, safi)) == NULL)
return 0;
length = length_from_afi(afi);
if (!length_from_afi(afi, &length))
return 0;
if (!make_addressRange(&aor, min, max, afi, length))
return 0;
@ -1258,7 +1265,7 @@ X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi,
{
int afi_len;
if ((afi_len = length_from_afi(afi)) == 0)
if (!length_from_afi(afi, &afi_len))
return 0;
if (length < afi_len)
@ -1401,7 +1408,8 @@ IPAddressOrRanges_canonize(IPAddressOrRanges *aors, const unsigned afi)
unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN];
int i, j, length;
length = length_from_afi(afi);
if (!length_from_afi(afi, &length))
return 0;
/*
* Sort the IPAddressOrRanges sequence.
@ -1548,7 +1556,8 @@ v2i_IPAddrBlocks(const struct v3_ext_method *method, struct v3_ext_ctx *ctx,
break;
}
length = length_from_afi(afi);
if (!length_from_afi(afi, &length))
goto err;
/*
* Handle SAFI, if any, and strdup() so we can null-terminate
@ -1658,7 +1667,7 @@ v2i_IPAddrBlocks(const struct v3_ext_method *method, struct v3_ext_ctx *ctx,
X509V3_conf_err(val);
goto err;
}
if (memcmp(min, max, length_from_afi(afi)) > 0) {
if (memcmp(min, max, length) > 0) {
X509V3error(X509V3_R_EXTENSION_VALUE_ERROR);
X509V3_conf_err(val);
goto err;