sign.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
  2. /*
  3. * Copyright (C) 2025 Google LLC.
  4. */
  5. #ifndef _GNU_SOURCE
  6. #define _GNU_SOURCE
  7. #endif
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <stdint.h>
  11. #include <stdbool.h>
  12. #include <string.h>
  13. #include <getopt.h>
  14. #include <err.h>
  15. #include <openssl/opensslv.h>
  16. #include <openssl/bio.h>
  17. #include <openssl/evp.h>
  18. #include <openssl/pem.h>
  19. #include <openssl/err.h>
  20. #include <openssl/cms.h>
  21. #include <linux/keyctl.h>
  22. #include <errno.h>
  23. #include <bpf/skel_internal.h>
  24. #include "main.h"
  25. #define OPEN_SSL_ERR_BUF_LEN 256
  26. /* Use deprecated in 3.0 ERR_get_error_line_data for openssl < 3 */
  27. #if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
  28. #define ERR_get_error_all(file, line, func, data, flags) \
  29. ERR_get_error_line_data(file, line, data, flags)
  30. #endif
  31. static void display_openssl_errors(int l)
  32. {
  33. char buf[OPEN_SSL_ERR_BUF_LEN];
  34. const char *file;
  35. const char *data;
  36. unsigned long e;
  37. int flags;
  38. int line;
  39. while ((e = ERR_get_error_all(&file, &line, NULL, &data, &flags))) {
  40. ERR_error_string_n(e, buf, sizeof(buf));
  41. if (data && (flags & ERR_TXT_STRING)) {
  42. p_err("OpenSSL %s: %s:%d: %s", buf, file, line, data);
  43. } else {
  44. p_err("OpenSSL %s: %s:%d", buf, file, line);
  45. }
  46. }
  47. }
  48. #define DISPLAY_OSSL_ERR(cond) \
  49. do { \
  50. bool __cond = (cond); \
  51. if (__cond && ERR_peek_error()) \
  52. display_openssl_errors(__LINE__);\
  53. } while (0)
  54. static EVP_PKEY *read_private_key(const char *pkey_path)
  55. {
  56. EVP_PKEY *private_key = NULL;
  57. BIO *b;
  58. b = BIO_new_file(pkey_path, "rb");
  59. private_key = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
  60. BIO_free(b);
  61. DISPLAY_OSSL_ERR(!private_key);
  62. return private_key;
  63. }
  64. static X509 *read_x509(const char *x509_name)
  65. {
  66. unsigned char buf[2];
  67. X509 *x509 = NULL;
  68. BIO *b;
  69. int n;
  70. b = BIO_new_file(x509_name, "rb");
  71. if (!b)
  72. goto cleanup;
  73. /* Look at the first two bytes of the file to determine the encoding */
  74. n = BIO_read(b, buf, 2);
  75. if (n != 2)
  76. goto cleanup;
  77. if (BIO_reset(b) != 0)
  78. goto cleanup;
  79. if (buf[0] == 0x30 && buf[1] >= 0x81 && buf[1] <= 0x84)
  80. /* Assume raw DER encoded X.509 */
  81. x509 = d2i_X509_bio(b, NULL);
  82. else
  83. /* Assume PEM encoded X.509 */
  84. x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
  85. cleanup:
  86. BIO_free(b);
  87. DISPLAY_OSSL_ERR(!x509);
  88. return x509;
  89. }
  90. __u32 register_session_key(const char *key_der_path)
  91. {
  92. unsigned char *der_buf = NULL;
  93. X509 *x509 = NULL;
  94. int key_id = -1;
  95. int der_len;
  96. if (!key_der_path)
  97. return key_id;
  98. x509 = read_x509(key_der_path);
  99. if (!x509)
  100. goto cleanup;
  101. der_len = i2d_X509(x509, &der_buf);
  102. if (der_len < 0)
  103. goto cleanup;
  104. key_id = syscall(__NR_add_key, "asymmetric", key_der_path, der_buf,
  105. (size_t)der_len, KEY_SPEC_SESSION_KEYRING);
  106. cleanup:
  107. X509_free(x509);
  108. OPENSSL_free(der_buf);
  109. DISPLAY_OSSL_ERR(key_id == -1);
  110. return key_id;
  111. }
  112. int bpftool_prog_sign(struct bpf_load_and_run_opts *opts)
  113. {
  114. BIO *bd_in = NULL, *bd_out = NULL;
  115. EVP_PKEY *private_key = NULL;
  116. CMS_ContentInfo *cms = NULL;
  117. long actual_sig_len = 0;
  118. X509 *x509 = NULL;
  119. int err = 0;
  120. bd_in = BIO_new_mem_buf(opts->insns, opts->insns_sz);
  121. if (!bd_in) {
  122. err = -ENOMEM;
  123. goto cleanup;
  124. }
  125. private_key = read_private_key(private_key_path);
  126. if (!private_key) {
  127. err = -EINVAL;
  128. goto cleanup;
  129. }
  130. x509 = read_x509(cert_path);
  131. if (!x509) {
  132. err = -EINVAL;
  133. goto cleanup;
  134. }
  135. cms = CMS_sign(NULL, NULL, NULL, NULL,
  136. CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED |
  137. CMS_STREAM);
  138. if (!cms) {
  139. err = -EINVAL;
  140. goto cleanup;
  141. }
  142. if (!CMS_add1_signer(cms, x509, private_key, EVP_sha256(),
  143. CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP |
  144. CMS_USE_KEYID | CMS_NOATTR)) {
  145. err = -EINVAL;
  146. goto cleanup;
  147. }
  148. if (CMS_final(cms, bd_in, NULL, CMS_NOCERTS | CMS_BINARY) != 1) {
  149. err = -EIO;
  150. goto cleanup;
  151. }
  152. EVP_Digest(opts->insns, opts->insns_sz, opts->excl_prog_hash,
  153. &opts->excl_prog_hash_sz, EVP_sha256(), NULL);
  154. bd_out = BIO_new(BIO_s_mem());
  155. if (!bd_out) {
  156. err = -ENOMEM;
  157. goto cleanup;
  158. }
  159. if (!i2d_CMS_bio_stream(bd_out, cms, NULL, 0)) {
  160. err = -EIO;
  161. goto cleanup;
  162. }
  163. actual_sig_len = BIO_get_mem_data(bd_out, NULL);
  164. if (actual_sig_len <= 0) {
  165. err = -EIO;
  166. goto cleanup;
  167. }
  168. if ((size_t)actual_sig_len > opts->signature_sz) {
  169. err = -ENOSPC;
  170. goto cleanup;
  171. }
  172. if (BIO_read(bd_out, opts->signature, actual_sig_len) != actual_sig_len) {
  173. err = -EIO;
  174. goto cleanup;
  175. }
  176. opts->signature_sz = actual_sig_len;
  177. cleanup:
  178. BIO_free(bd_out);
  179. CMS_ContentInfo_free(cms);
  180. X509_free(x509);
  181. EVP_PKEY_free(private_key);
  182. BIO_free(bd_in);
  183. DISPLAY_OSSL_ERR(err < 0);
  184. return err;
  185. }