Changeset 104745 in vbox for trunk/src/VBox/Runtime/common/crypto
- Timestamp:
- May 21, 2024 12:52:09 PM (8 months ago)
- Location:
- trunk/src/VBox/Runtime/common/crypto
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/crypto/iprt-openssl.cpp
r98103 r104745 43 43 #ifdef IPRT_WITH_OPENSSL /* Whole file. */ 44 44 # include <iprt/err.h> 45 # include <iprt/file.h> 45 46 # include <iprt/string.h> 46 47 # include <iprt/mem.h> … … 169 170 } 170 171 172 171 173 DECLHIDDEN(int) rtCrOpenSslConvertPkcs7Attribute(void **ppvOsslAttrib, PCRTCRPKCS7ATTRIBUTE pAttrib, PRTERRINFO pErrInfo) 172 174 { 173 const unsigned char *pabEncoded ;174 uint32_t cbEncoded ;175 void *pvFree ;175 const unsigned char *pabEncoded = NULL; 176 uint32_t cbEncoded = 0; 177 void *pvFree = NULL; 176 178 int rc = RTAsn1EncodeQueryRawBits(RTCrPkcs7Attribute_GetAsn1Core(pAttrib), 177 179 (const uint8_t **)&pabEncoded, &cbEncoded, &pvFree, pErrInfo); … … 199 201 200 202 203 /** 204 * Writes the content of the @a pvMemBio to the new file @a pszFilename. 205 * 206 * @returns IPRT status code. 207 * @param pvMemBio The memory BIO to write out. 208 * @param pszFilename The destination file. This will be created. 209 * The function will fail if this already exists. 210 * @param pErrInfo Where to provide additional error details. Optional. 211 */ 212 DECLHIDDEN(int) rtCrOpenSslWriteMemBioToNewFile(void *pvMemBio, const char *pszFilename, PRTERRINFO pErrInfo) 213 { 214 int rc; 215 216 /* Get the BIO buffer pointer first. */ 217 BUF_MEM *pBioBuf = NULL; 218 long rcOssl = BIO_get_mem_ptr((BIO *)pvMemBio, &pBioBuf); 219 if (rcOssl > 0) 220 { 221 AssertPtr(pBioBuf); 222 RTFILE hFile = NIL_RTFILE; 223 rc = RTFileOpen(&hFile, pszFilename, 224 RTFILE_O_WRITE | RTFILE_O_DENY_ALL | RTFILE_O_CREATE | (0600 << RTFILE_O_CREATE_MODE_SHIFT)); 225 if (RT_SUCCESS(rc)) 226 { 227 rc = RTFileWrite(hFile, pBioBuf->data, pBioBuf->length, NULL); 228 if (RT_SUCCESS(rc)) 229 { 230 rc = RTFileClose(hFile); 231 AssertRCStmt(rc, rc = RTErrInfoSetF(pErrInfo, rc, "RTFileClose failed on '%s'", pszFilename)); 232 } 233 else 234 { 235 rc = RTErrInfoSetF(pErrInfo, rc, "RTFileWrite(,,%#zx,) failed on '%s'", pBioBuf->length, pszFilename); 236 RTFileClose(hFile); 237 } 238 if (RT_FAILURE(rc)) 239 RTFileDelete(pszFilename); 240 } 241 else 242 rc = RTErrInfoSetF(pErrInfo, rc, "RTFileOpen failed on '%s'", pszFilename); 243 } 244 else 245 rc = RTErrInfoSet(pErrInfo, VERR_GENERAL_FAILURE, "BIO_get_mem_ptr"); 246 return rc; 247 } 248 249 201 250 #endif /* IPRT_WITH_OPENSSL */ 202 251 -
trunk/src/VBox/Runtime/common/crypto/x509-create-sign.cpp
r104574 r104745 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Crypto - X.509, Certificate Creation and Signing.3 * IPRT - Crypto - X.509, Certificate Creation. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 20 06-2023Oracle and/or its affiliates.7 * Copyright (C) 2024 Oracle and/or its affiliates. 8 8 * 9 9 * This file is part of VirtualBox base platform packages, as … … 39 39 * Header Files * 40 40 *********************************************************************************************************************************/ 41 42 # if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)43 # include <io.h>44 # endif45 46 #include <iprt/file.h>47 41 #include "internal/iprt.h" 48 42 #include <iprt/crypto/x509.h> 49 43 50 # ifdef _MSC_VER51 # define IPRT_COMPILER_VCC_WITH_C_INIT_TERM_SECTIONS52 # include "internal/compiler-vcc.h"53 # endif54 55 # if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)56 # include <fcntl.h>57 # endif58 #include <iprt/err.h>59 #include <iprt/string.h>60 61 44 #ifdef IPRT_WITH_OPENSSL 45 # include <iprt/err.h> 46 # include <iprt/file.h> 47 # include <iprt/rand.h> 48 49 # include "internal/iprt-openssl.h" 50 # include "internal/openssl-pre.h" 62 51 # include <openssl/evp.h> 63 52 # include <openssl/pem.h> 64 53 # include <openssl/x509.h> 65 54 # include <openssl/bio.h> 66 67 #if defined(RT_OS_OS2) 68 # define _O_WRONLY O_WRONLY 69 #endif 70 71 RTDECL(int) RTCrX509Certificate_Generate(const char *pszServerCertificate, const char *pszServerPrivateKey) 55 # include "internal/openssl-post.h" 56 57 58 59 RTDECL(int) RTCrX509Certificate_GenerateSelfSignedRsa(RTDIGESTTYPE enmDigestType, uint32_t cBits, uint32_t cSecsValidFor, 60 uint32_t fKeyUsage, uint64_t fExtKeyUsage, void *pvSubjectTodo, 61 const char *pszCertFile, const char *pszPrivateKeyFile, PRTERRINFO pErrInfo) 72 62 { 73 int rc = VINF_SUCCESS; 63 AssertReturn(cSecsValidFor <= (uint32_t)INT32_MAX, VERR_OUT_OF_RANGE); /* larger values are not portable (win) */ 64 AssertReturn(!fKeyUsage, VERR_NOT_IMPLEMENTED); 65 AssertReturn(!fExtKeyUsage, VERR_NOT_IMPLEMENTED); 66 AssertReturn(pvSubjectTodo == NULL, VERR_NOT_IMPLEMENTED); 67 74 68 /* 75 * Set up private key using rsa69 * Translate enmDigestType. 76 70 */ 77 EVP_PKEY * pkey; 78 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) /* OpenSSL 3 needed */ 79 pkey = EVP_RSA_gen(2048); 80 #else 81 pkey = EVP_PKEY_new(); 82 RSA * rsa; 83 rsa = RSA_generate_key( 84 2048, /* Number of bits for the key */ 71 const EVP_MD * const pEvpDigest = (const EVP_MD *)rtCrOpenSslConvertDigestType(enmDigestType, pErrInfo); 72 AssertReturn(pEvpDigest, pErrInfo ? pErrInfo->rc : VERR_CR_DIGEST_NOT_SUPPORTED); 73 74 /* 75 * Create a new RSA private key. 76 */ 77 # if OPENSSL_VERSION_NUMBER >= 0x30000000 /* RSA_generate_key is depreated in v3 */ 78 EVP_PKEY * const pPrivateKey = EVP_RSA_gen(cBits); 79 if (!pPrivateKey) 80 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_GEN_FAILED_RSA, "EVP_RSA_gen(%u) failed", cBits); 81 # else 82 RSA * const pRsaKey = RSA_generate_key( 83 cBits, /* Number of bits for the key */ 85 84 RSA_F4, /* Exponent - RSA_F4 is defined as 0x10001L */ 86 85 NULL, /* Callback */ 87 86 NULL /* Callback argument */ 88 87 ); 89 EVP_PKEY_assign_RSA(pkey, rsa); 90 #endif 91 92 if ( pkey == NULL ) 93 return VERR_CR_KEY_GEN_FAILED_RSA; 88 if (!pRsaKey) 89 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_GEN_FAILED_RSA, "RSA_generate_key(%u,RSA_F4,,) failed", cBits); 90 91 EVP_PKEY * const pPrivateKey = EVP_PKEY_new(); 92 if (pPrivateKey) 93 EVP_PKEY_assign_RSA(pPrivateKey, pRsaKey); /* Takes ownership of pRsaKey. */ 94 else 95 { 96 RSA_free(pRsaKey); 97 return RTErrInfoSet(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new failed"); 98 } 99 # endif 94 100 95 101 /* 96 * Set up certificate102 * Construct the certificate. 97 103 */ 98 X509* tempX509 = X509_new(); 99 if ( tempX509 == NULL ) 100 return VERR_CR_X509_GENERIC_ERROR; 101 X509_set_version(tempX509,0); /** Set to X509 version 1 */ 102 ASN1_INTEGER_set(X509_get_serialNumber(tempX509), 1); 103 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) 104 X509_gmtime_adj(X509_getm_notBefore(tempX509), 0); 105 X509_gmtime_adj(X509_getm_notAfter(tempX509), 60*60*24*3650); /** 10 years time */ 106 #else 107 X509_gmtime_adj(X509_get_notBefore(tempX509), 0); 108 X509_gmtime_adj(X509_get_notAfter(tempX509), 60*60*24*3650); /** 10 years time */ 109 #endif 110 X509_set_pubkey(tempX509,pkey); 111 112 X509_NAME *x509_name = NULL; 113 x509_name = X509_get_subject_name(tempX509); 114 115 rc = X509_set_issuer_name(tempX509, x509_name); 116 if ( RT_FAILURE(rc) ) 117 return rc; 118 119 rc = X509_sign( tempX509, pkey, EVP_sha1()); 120 if ( RT_FAILURE(rc) ) 121 return rc; 122 123 RTFILE hKeyFile; 124 rc = RTFileOpen(&hKeyFile, pszServerPrivateKey, RTFILE_O_WRITE | RTFILE_O_DENY_ALL | RTFILE_O_CREATE | (0600 << RTFILE_O_CREATE_MODE_SHIFT) ); 125 if ( RT_FAILURE(rc) ) 126 return rc; 127 # ifndef _MSC_VER 128 int fd1 = (int)RTFileToNative(hKeyFile); 104 int rc = VINF_SUCCESS; 105 X509 *pNewCert = X509_new(); 106 if (pNewCert) 107 { 108 int rcOssl; 109 110 /* Set to X509 version 1: */ 111 # if 0 112 if (fKeyUsage || fExtKeyUsage) 113 rcOssl = X509_set_version(pNewCert, RTCRX509TBSCERTIFICATE_V3); 114 else 115 # endif 116 rcOssl = X509_set_version(pNewCert, RTCRX509TBSCERTIFICATE_V1); 117 AssertStmt(rcOssl > 0, rc = RTErrInfoSet(pErrInfo, VERR_GENERAL_FAILURE, "X509_set_version failed")); 118 119 /* Set the serial number to a random number in the 1 - 1G range: */ 120 rcOssl = ASN1_INTEGER_set(X509_get_serialNumber(pNewCert), RTRandU32Ex(1, UINT32_MAX / 4)); 121 AssertStmt(rcOssl > 0, rc = RTErrInfoSet(pErrInfo, VERR_GENERAL_FAILURE, "X509_set_version failed")); 122 123 /* The certificate is valid from now and the specifice number of seconds forwards: */ 124 # if OPENSSL_VERSION_NUMBER >= 0x30000000 125 AssertStmt(X509_gmtime_adj(X509_getm_notBefore(pNewCert), 0), 126 rc = RTErrInfoSet(pErrInfo, VERR_GENERAL_FAILURE, "X509_gmtime_adj/before failed")); 127 AssertStmt(X509_gmtime_adj(X509_getm_notAfter(pNewCert), cSecsValidFor), 128 rc = RTErrInfoSet(pErrInfo, VERR_GENERAL_FAILURE, "X509_gmtime_adj/after failed")); 129 129 # else 130 int fd1 = _open_osfhandle(RTFileToNative(hKeyFile), _O_WRONLY); 131 # endif 132 if ( fd1 < 0 ) 133 return VERR_FILE_IO_ERROR; 134 135 BIO *fp1 = BIO_new_fd(fd1, BIO_NOCLOSE); 136 rc = PEM_write_bio_PrivateKey( fp1, pkey, NULL, NULL, 0, NULL, NULL); 137 if ( RT_FAILURE(rc) ) 138 return rc; 139 BIO_free(fp1); 140 # ifdef _MSC_VER 141 close(fd1); 142 #endif 143 RTFileClose(hKeyFile); 144 145 RTFILE hCertFile; 146 rc = RTFileOpen(&hCertFile, pszServerCertificate, RTFILE_O_WRITE | RTFILE_O_DENY_ALL | RTFILE_O_CREATE | (0600 << RTFILE_O_CREATE_MODE_SHIFT) ); 147 if ( RT_FAILURE(rc) ) 148 return rc; 149 # ifndef _MSC_VER 150 int fd2 = (int)RTFileToNative(hCertFile); 151 # else 152 int fd2 = _open_osfhandle(RTFileToNative(hCertFile), _O_WRONLY); 153 # endif 154 if ( fd2 < 0 ) 155 return VERR_FILE_IO_ERROR; 156 157 BIO *fp2 = BIO_new_fd(fd2, BIO_NOCLOSE); 158 rc = PEM_write_bio_X509( fp2, tempX509 ); 159 if ( RT_FAILURE(rc) ) 160 return rc; 161 BIO_free(fp2); 162 # ifdef _MSC_VER 163 close(fd2); 164 #endif 165 RTFileClose(hCertFile); 166 167 X509_free(tempX509); 168 EVP_PKEY_free(pkey); 169 130 AssertStmt(X509_gmtime_adj(X509_get_notBefore(pNewCert), 0), 131 rc = RTErrInfoSet(pErrInfo, VERR_GENERAL_FAILURE, "X509_gmtime_adj/before failed")); 132 AssertStmt(X509_gmtime_adj(X509_get_notAfter(pNewCert), cSecsValidFor), 133 rc = RTErrInfoSet(pErrInfo, VERR_GENERAL_FAILURE, "X509_gmtime_adj/after failed")); 134 # endif 135 136 /* Set the public key (part of the private): */ 137 rcOssl = X509_set_pubkey(pNewCert, pPrivateKey); 138 AssertStmt(rcOssl > 0, rc = RTErrInfoSet(pErrInfo, VERR_GENERAL_FAILURE, "X509_set_pubkey failed")); 139 140 # if 0 141 /* Set key usage. */ 142 if (fKeyUsage) 143 { 144 } 145 /* Set extended key usage. */ 146 if (fExtKeyUsage) 147 { 148 } 149 # endif 150 /** @todo set other certificate attributes? */ 151 152 153 /** @todo check what the subject name is... Offer way to specify it? */ 154 155 /* Make it self signed: */ 156 X509_NAME *pX509Name = X509_get_subject_name(pNewCert); 157 rcOssl = X509_set_issuer_name(pNewCert, pX509Name); 158 AssertStmt(rcOssl > 0, rc = RTErrInfoSet(pErrInfo, VERR_GENERAL_FAILURE, "X509_set_issuer_name failed")); 159 160 if (RT_SUCCESS(rc)) 161 { 162 /* 163 * Sign the certificate. 164 */ 165 rcOssl = X509_sign(pNewCert, pPrivateKey, pEvpDigest); 166 if (rcOssl > 0) 167 { 168 /* 169 * Write out the result to the two files. 170 */ 171 /* The certificate (not security sensitive). */ 172 BIO * const pCertBio = BIO_new(BIO_s_mem()); 173 if (pCertBio) 174 { 175 rcOssl = PEM_write_bio_X509(pCertBio, pNewCert); 176 if (rcOssl > 0) 177 rc = rtCrOpenSslWriteMemBioToNewFile(pCertBio, pszCertFile, pErrInfo); 178 else 179 rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_GEN_FAILED_RSA, "PEM_write_bio_X509 failed"); 180 BIO_free(pCertBio); 181 } 182 else 183 rc = VERR_NO_MEMORY; 184 185 if (RT_SUCCESS(rc)) 186 { 187 /* The private key as plain text (security sensitive, thus last). */ 188 BIO * const pPkBio = BIO_new(BIO_s_secmem()); 189 if (pPkBio) 190 { 191 rcOssl = PEM_write_bio_PrivateKey(pPkBio, pPrivateKey, 192 NULL /*enc*/, NULL /*kstr*/, 0 /*klen*/, NULL /*cb*/, NULL /*u*/); 193 if (rcOssl > 0) 194 rc = rtCrOpenSslWriteMemBioToNewFile(pPkBio, pszPrivateKeyFile, pErrInfo); 195 else 196 rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_GEN_FAILED_RSA, "PEM_write_bio_PrivateKey failed"); 197 BIO_free(pPkBio); 198 } 199 else 200 rc = VERR_NO_MEMORY; 201 if (RT_FAILURE(rc)) 202 RTFileDelete(pszCertFile); 203 } 204 } 205 else 206 rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_GEN_FAILED_RSA, "X509_sign failed"); 207 } 208 209 X509_free(pNewCert); 210 } 211 else 212 rc = RTErrInfoSet(pErrInfo, VERR_NO_MEMORY, "X509_new failed"); 213 214 EVP_PKEY_free(pPrivateKey); 170 215 return rc; 171 216 }
Note:
See TracChangeset
for help on using the changeset viewer.