💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › a03ad9a68a5e10b0d67164cac7c25… captured on 2023-12-28 at 15:42:11. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

Go Back

0 /*

1 * ISC License

2 * Copyright (c) 2023 RMF <rawmonk@firemail.cc>

3 */

4 #include <stdlib.h>

5 #include <string.h>

6 #include <openssl/pem.h>

7 #include <openssl/err.h>

8 #include <fcntl.h>

9 #ifdef __linux__

10 #include <sys/random.h>

11 #endif

12 #include "storage.h"

13 #include "strlcpy.h"

14 #include "config.h"

15

16 int certificate_getpath(const char *host, char *crt, size_t crt_len,

17 char *key, size_t key_len) {

18 int len = strnlen(host, 1024);

19 if (strlcpy(crt, host, crt_len) >= crt_len - 4) return -1;

20 if (strlcpy(key, host, key_len) >= key_len - 4) return -1;

21 if (strlcpy(&crt[len], ".crt", crt_len - len) + len >= crt_len)

22 return -1;

23 if (strlcpy(&key[len], ".key", key_len - len) + len >= key_len)

24 return -1;

25 return len + 4;

26 }

27

28 int certificate_create(char *host, char *error, int errlen) {

29

30 char key[1024];

31 char crt[1024];

32 FILE* f = NULL;

33 int fd, id, ret = 1;

34

35 X509_NAME *name;

36 #ifdef USE_OPENSSL

37 EVP_PKEY *pkey = EVP_RSA_gen(CERTIFICATE_BITS);

38 X509 *x509 = X509_new();

39 #else /* LibreSSL */

40 EVP_PKEY *pkey = EVP_PKEY_new();

41 RSA *rsa = RSA_new();

42 BIGNUM *bne = BN_new();

43 X509 *x509 = X509_new();

44 if (BN_set_word(bne, 65537) != 1) goto failed;

45 if (RSA_generate_key_ex(rsa, config.certificateBits, bne, NULL) != 1)

46 goto failed;

47

48 EVP_PKEY_assign_RSA(pkey, rsa);

49 #endif

50

51 #ifdef __linux__

52 getrandom(&id, sizeof(id), GRND_RANDOM);

53 #else

54 arc4random_buf(&id, sizeof(id));

55 #endif

56 if (ASN1_INTEGER_set(X509_get_serialNumber(x509), id) != 1)

57 goto failed;

58

59 X509_gmtime_adj(X509_getm_notBefore(x509), 0);

60 X509_gmtime_adj(X509_getm_notAfter(x509), config.certificateLifespan);

61

62 if (X509_set_pubkey(x509, pkey) != 1) goto failed;

63

64 name = X509_get_subject_name(x509);

65 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,

66 (unsigned char*)host, -1, -1, 0) != 1)

67 goto failed;

68

69 if (X509_set_issuer_name(x509, name) != 1) goto failed;

70 if (X509_sign(x509, pkey, EVP_sha1()) == 0) goto failed;

71

72 if (certificate_getpath(host, crt, sizeof(crt),

73 key, sizeof(key)) == -1)

74 goto failed;

75

76 /* Key */

77 fd = storage_open(key, O_CREAT|O_WRONLY|O_TRUNC, 0600);

78 if (fd < 0) {

79 snprintf(error, errlen, "Failed to open %s : %s",

80 key, strerror(errno));

81 goto skip_error;

82 }

83 f = fdopen(fd, "wb");

84

85 if (!f) {

86 snprintf(error, errlen, "Failed to write to %s : %s",

87 key, strerror(errno));

88 goto skip_error;

89 }

90 if (PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL) != 1)

91 goto failed;

92 fclose(f);

93

94 /* Certificate */

95 fd = storage_open(crt, O_CREAT|O_WRONLY|O_TRUNC, 0600);

96 if (fd < 0) {

97 snprintf(error, errlen, "Failed to open %s", crt);

98 goto skip_error;

99 }

100 f = fdopen(fd, "wb");

101

102 if (!f) {

103 snprintf(error, errlen, "Failed to write to %s", crt);

104 goto skip_error;

105 }

106 if (PEM_write_X509(f, x509) != 1)

107 goto failed;

108 fclose(f);

109

110 f = NULL;

111 ret = 0;

112 goto skip_error;

113 failed:

114 snprintf(error, errlen, "Failed to generate certificate");

115 skip_error:

116 if (f) fclose(f);

117 EVP_PKEY_free(pkey);

118 X509_free(x509);

119 #ifndef USE_OPENSSL

120 BN_free(bne);

121 #endif

122 return ret;

123 }

124