Hello,
for a project I needed to extend a self signed certificate with some extensions using OpenSSL version 1.1. Attached are two patches:
0001-Add-types-and-funtions-that-are-needed-fo-adding-ext.patch adds necessary types and functions for OpenSSL so extensions can be added.
0002-Add-utility-function-X509AddExtension-for-adding-ext.patch adds the utility function X509AddExtension for easing the process of adding an extension to a certificate.
When used, a function for creating a self signed certificate can look like this:
function CreateSelfSignedCert(const HostName, Country: String; const ValidDays: Integer; out Certificate, Key: RawBytestring): Boolean;
var
pk: EVP_PKEY;
x: PX509;
rsa: PRSA;
t: PASN1_UTCTIME;
name: PX509_NAME;
b: PBIO;
xn, y: integer;
s: AnsiString;
begin
Result := True;
pk := EvpPkeynew;
x := X509New;
try
rsa := RsaGenerateKey(2048, $10001, nil, nil);
EvpPkeyAssign(pk, EVP_PKEY_RSA, rsa);
X509SetVersion(x, 2);
// Asn1IntegerSet(X509getSerialNumber(x), 0);
Asn1IntegerSet(X509getSerialNumber(x), GetTick);
t := Asn1UtctimeNew;
try
X509GmtimeAdj(t, -60 * 60 *24);
X509SetNotBefore(x, t);
X509GmtimeAdj(t, ValidDays * 60 * 60 *24);
X509SetNotAfter(x, t);
finally
Asn1UtctimeFree(t);
end;
X509SetPubkey(x, pk);
Name := X509GetSubjectName(x);
X509NameAddEntryByTxt(Name, 'C', $1001, Country, -1, -1, 0);
X509NameAddEntryByTxt(Name, 'CN', $1001, HostName, -1, -1, 0);
X509AddExtension(x, NID_ext_key_usage, 'serverAuth,clientAuth');
X509AddExtension(x, NID_subject_alt_name, 'DNS:' + HostName);
X509AddExtension(x, NID_basic_constraints, 'CA:true');
x509SetIssuerName(x, Name);
x509Sign(x, pk, EvpGetDigestByName('SHA256'));
b := BioNew(BioSMem);
try
i2dX509Bio(b, x);
xn := bioctrlpending(b);
setlength(s, xn);
y := bioread(b, s, xn);
if y > 0 then
setlength(s, y);
finally
BioFreeAll(b);
end;
Certificate := s;
b := BioNew(BioSMem);
try
i2dPrivatekeyBio(b, pk);
xn := bioctrlpending(b);
setlength(s, xn);
y := bioread(b, s, xn);
if y > 0 then
setlength(s, y);
finally
BioFreeAll(b);
end;
Key := s;
finally
X509free(x);
EvpPkeyFree(pk);
end;
end;
Note: X509V3_EXT_conf_nid seems to not be documented and isn't exported with OpenSSL version 3.1 (maybe earlier) anymore. The official way seems to be to use X509_EXTENSION_create_by_NID. An example on how to use that can be found on
https://github.com/openssl/openssl/issues/11706#issuecomment-623791405