pem.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. /*
  2. *
  3. * Embedded Linux library
  4. *
  5. * Copyright (C) 2015 Intel Corporation. All rights reserved.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #define _GNU_SOURCE
  26. #include <fcntl.h>
  27. #include <unistd.h>
  28. #include <sys/mman.h>
  29. #include <strings.h>
  30. #include <errno.h>
  31. #include "useful.h"
  32. #include "private.h"
  33. #include "key.h"
  34. #include "cert.h"
  35. #include "queue.h"
  36. #include "pem.h"
  37. #include "base64.h"
  38. #include "utf8.h"
  39. #include "asn1-private.h"
  40. #include "cipher.h"
  41. #include "cert-private.h"
  42. #include "missing.h"
  43. #include "pem-private.h"
  44. #define PEM_START_BOUNDARY "-----BEGIN "
  45. #define PEM_END_BOUNDARY "-----END "
  46. static const char *is_start_boundary(const void *buf, size_t buf_len,
  47. size_t *label_len)
  48. {
  49. const char *start, *end, *ptr;
  50. int prev_special, special;
  51. const char *buf_ptr = buf;
  52. if (buf_len < strlen(PEM_START_BOUNDARY))
  53. return NULL;
  54. /* Check we have a "-----BEGIN " (RFC7468 section 2) */
  55. if (memcmp(buf, PEM_START_BOUNDARY, strlen(PEM_START_BOUNDARY)))
  56. return NULL;
  57. /*
  58. * Check we have a string of printable characters in which no
  59. * two consecutive characters are "special" nor is the first or the
  60. * final character "special". These special characters are space
  61. * and hyphen. (RFC7468 section 3)
  62. * The loop will end on the second hyphen of the final "-----" if
  63. * no error found earlier.
  64. */
  65. start = buf + strlen(PEM_START_BOUNDARY);
  66. end = start;
  67. prev_special = 1;
  68. while (end < buf_ptr + buf_len && l_ascii_isprint(*end)) {
  69. special = *end == ' ' || *end == '-';
  70. if (prev_special && special)
  71. break;
  72. end++;
  73. prev_special = special;
  74. }
  75. /* Rewind to the first '-', but handle empty labels */
  76. if (end != start)
  77. end--;
  78. /* Check we have a "-----" (RFC7468 section 2) */
  79. if (end + 5 > buf_ptr + buf_len || memcmp(end, "-----", 5))
  80. return NULL;
  81. /* Check all remaining characters are horizontal whitespace (WSP) */
  82. for (ptr = end + 5; ptr < buf_ptr + buf_len; ptr++)
  83. if (*ptr != ' ' && *ptr != '\t')
  84. return NULL;
  85. *label_len = end - start;
  86. return start;
  87. }
  88. static bool is_end_boundary(const void *buf, size_t buf_len,
  89. const char *label, size_t label_len)
  90. {
  91. const char *buf_ptr = buf;
  92. size_t len = strlen(PEM_END_BOUNDARY) + label_len + 5;
  93. if (buf_len < len)
  94. return false;
  95. if (memcmp(buf_ptr, PEM_END_BOUNDARY, strlen(PEM_END_BOUNDARY)) ||
  96. memcmp(buf_ptr + strlen(PEM_END_BOUNDARY),
  97. label, label_len) ||
  98. memcmp(buf_ptr + (len - 5), "-----", 5))
  99. return false;
  100. /* Check all remaining characters are horizontal whitespace (WSP) */
  101. for (; len < buf_len; len++)
  102. if (buf_ptr[len] != ' ' && buf_ptr[len] != '\t')
  103. return false;
  104. return true;
  105. }
  106. const char *pem_next(const void *buf, size_t buf_len, char **type_label,
  107. size_t *base64_len,
  108. const char **endp, bool strict)
  109. {
  110. const char *buf_ptr = buf;
  111. const char *base64_data = NULL, *eol;
  112. const char *label = NULL;
  113. size_t label_len = 0;
  114. const char *start = NULL;
  115. /*
  116. * The base64 parser uses the RFC7468 laxbase64text grammar but we
  117. * do full checks on the encapsulation boundary lines, i.e. no
  118. * leading spaces allowed, making sure quoted text and similar
  119. * are not confused for actual PEM "textual encoding".
  120. */
  121. while (buf_len) {
  122. for (eol = buf_ptr; eol < buf_ptr + buf_len; eol++)
  123. if (*eol == '\r' || *eol == '\n')
  124. break;
  125. if (!base64_data) {
  126. label = is_start_boundary(buf_ptr, eol - buf_ptr,
  127. &label_len);
  128. if (label) {
  129. start = label - strlen("-----BEGIN ");
  130. base64_data = eol;
  131. } else if (strict)
  132. break;
  133. } else if (start && is_end_boundary(buf_ptr, eol - buf_ptr,
  134. label, label_len)) {
  135. if (type_label)
  136. *type_label = l_strndup(label, label_len);
  137. if (base64_len)
  138. *base64_len = buf_ptr - base64_data;
  139. if (endp) {
  140. if (eol == buf + buf_len)
  141. *endp = eol;
  142. else
  143. *endp = eol + 1;
  144. }
  145. return base64_data;
  146. }
  147. if (eol == buf_ptr + buf_len)
  148. break;
  149. buf_len -= eol + 1 - buf_ptr;
  150. buf_ptr = eol + 1;
  151. if (buf_len && *eol == '\r' && *buf_ptr == '\n') {
  152. buf_ptr++;
  153. buf_len--;
  154. }
  155. }
  156. /* If we found no label signal EOF rather than parse error */
  157. if (!base64_data && endp)
  158. *endp = NULL;
  159. return NULL;
  160. }
  161. uint8_t *pem_load_buffer(const void *buf, size_t buf_len,
  162. char **out_type_label, size_t *out_len,
  163. char **out_headers, const char **out_endp)
  164. {
  165. size_t base64_len;
  166. const char *base64;
  167. char *label;
  168. const char *headers = NULL;
  169. size_t headers_len;
  170. uint8_t *ret;
  171. base64 = pem_next(buf, buf_len, &label, &base64_len,
  172. out_endp, false);
  173. if (!base64)
  174. return NULL;
  175. if (memchr(base64, ':', base64_len)) {
  176. const char *start;
  177. const char *end;
  178. while (base64_len && l_ascii_isspace(*base64)) {
  179. base64++;
  180. base64_len--;
  181. }
  182. start = base64;
  183. if (!(end = memmem(start, base64_len, "\n\n", 2)) &&
  184. !(end = memmem(start, base64_len, "\n\r\n", 3)))
  185. goto err;
  186. /* Check that each header line has a key and a colon */
  187. while (start < end) {
  188. const char *lf = rawmemchr(start, '\n');
  189. const char *colon = memchr(start, ':', lf - start);
  190. if (!colon)
  191. goto err;
  192. for (; start < colon; start++)
  193. if (l_ascii_isalnum(*start))
  194. break;
  195. if (start == colon)
  196. goto err;
  197. start = lf + 1;
  198. }
  199. headers = base64;
  200. headers_len = end - base64;
  201. base64_len -= headers_len + 2;
  202. base64 = end + 2;
  203. }
  204. ret = l_base64_decode(base64, base64_len, out_len);
  205. if (ret) {
  206. *out_type_label = label;
  207. if (out_headers) {
  208. if (headers)
  209. *out_headers = l_strndup(headers, headers_len);
  210. else
  211. *out_headers = NULL;
  212. }
  213. return ret;
  214. }
  215. err:
  216. l_free(label);
  217. return NULL;
  218. }
  219. LIB_EXPORT uint8_t *l_pem_load_buffer(const void *buf, size_t buf_len,
  220. char **type_label, size_t *out_len)
  221. {
  222. return pem_load_buffer(buf, buf_len, type_label, out_len, NULL, NULL);
  223. }
  224. int pem_file_open(struct pem_file_info *info, const char *filename)
  225. {
  226. info->fd = open(filename, O_RDONLY);
  227. if (info->fd < 0)
  228. return -errno;
  229. if (fstat(info->fd, &info->st) < 0) {
  230. int r = -errno;
  231. close(info->fd);
  232. return r;
  233. }
  234. info->data = mmap(NULL, info->st.st_size,
  235. PROT_READ, MAP_SHARED, info->fd, 0);
  236. if (info->data == MAP_FAILED) {
  237. int r = -errno;
  238. close(info->fd);
  239. return r;
  240. }
  241. return 0;
  242. }
  243. void pem_file_close(struct pem_file_info *info)
  244. {
  245. munmap(info->data, info->st.st_size);
  246. close(info->fd);
  247. }
  248. static uint8_t *pem_load_file(const char *filename, char **out_type_label,
  249. size_t *out_len, char **out_headers)
  250. {
  251. struct pem_file_info file;
  252. uint8_t *result;
  253. if (unlikely(!filename))
  254. return NULL;
  255. if (pem_file_open(&file, filename) < 0)
  256. return NULL;
  257. result = pem_load_buffer(file.data, file.st.st_size,
  258. out_type_label, out_len, out_headers,
  259. NULL);
  260. pem_file_close(&file);
  261. return result;
  262. }
  263. LIB_EXPORT uint8_t *l_pem_load_file(const char *filename,
  264. char **out_type_label, size_t *out_len)
  265. {
  266. return pem_load_file(filename, out_type_label, out_len, NULL);
  267. }
  268. static struct l_certchain *pem_list_to_chain(struct l_queue *list)
  269. {
  270. struct l_certchain *chain;
  271. if (!list)
  272. return NULL;
  273. chain = certchain_new_from_leaf(l_queue_pop_head(list));
  274. while (!l_queue_isempty(list))
  275. certchain_link_issuer(chain, l_queue_pop_head(list));
  276. l_queue_destroy(list, NULL);
  277. return chain;
  278. }
  279. LIB_EXPORT struct l_certchain *l_pem_load_certificate_chain_from_data(
  280. const void *buf, size_t len)
  281. {
  282. struct l_queue *list = l_pem_load_certificate_list_from_data(buf, len);
  283. if (!list)
  284. return NULL;
  285. return pem_list_to_chain(list);
  286. }
  287. LIB_EXPORT struct l_certchain *l_pem_load_certificate_chain(
  288. const char *filename)
  289. {
  290. struct l_queue *list = l_pem_load_certificate_list(filename);
  291. if (!list)
  292. return NULL;
  293. return pem_list_to_chain(list);
  294. }
  295. static bool pem_write_one_cert(struct l_cert *cert, void *user_data)
  296. {
  297. int *fd = user_data;
  298. const uint8_t *der;
  299. size_t der_len;
  300. struct iovec iov[3];
  301. ssize_t r;
  302. der = l_cert_get_der_data(cert, &der_len);
  303. iov[0].iov_base = "-----BEGIN CERTIFICATE-----\n";
  304. iov[0].iov_len = strlen(iov[0].iov_base);
  305. iov[1].iov_base = l_base64_encode(der, der_len, 64, &iov[1].iov_len);
  306. iov[2].iov_base = "\n-----END CERTIFICATE-----\n";
  307. iov[2].iov_len = strlen(iov[2].iov_base);
  308. r = L_TFR(writev(*fd, iov, 3));
  309. l_free(iov[1].iov_base);
  310. if (r == (ssize_t) (iov[0].iov_len + iov[1].iov_len + iov[2].iov_len))
  311. return false;
  312. if (r < 0)
  313. *fd = -errno;
  314. else
  315. *fd = -EIO;
  316. return true;
  317. }
  318. int pem_write_certificate_chain(const struct l_certchain *chain,
  319. const char *filename)
  320. {
  321. int fd = L_TFR(open(filename, O_CREAT | O_WRONLY | O_CLOEXEC, 0600));
  322. int err = fd;
  323. if (err < 0)
  324. return -errno;
  325. l_certchain_walk_from_leaf((struct l_certchain *) chain,
  326. pem_write_one_cert, &err);
  327. close(fd);
  328. return err < 0 ? err : 0;
  329. }
  330. LIB_EXPORT struct l_queue *l_pem_load_certificate_list_from_data(
  331. const void *buf, size_t len)
  332. {
  333. const char *ptr, *end;
  334. struct l_queue *list = NULL;
  335. ptr = buf;
  336. end = buf + len;
  337. while (ptr && ptr < end) {
  338. uint8_t *der;
  339. size_t der_len;
  340. char *label = NULL;
  341. struct l_cert *cert;
  342. const char *base64;
  343. size_t base64_len;
  344. bool is_certificate;
  345. base64 = pem_next(ptr, end - ptr, &label,
  346. &base64_len, &ptr, false);
  347. if (!base64) {
  348. if (!ptr)
  349. break;
  350. /* if ptr was not reset to NULL; parse error */
  351. goto error;
  352. }
  353. is_certificate = !strcmp(label, "CERTIFICATE");
  354. l_free(label);
  355. if (!is_certificate)
  356. goto error;
  357. der = l_base64_decode(base64, base64_len, &der_len);
  358. if (!der)
  359. goto error;
  360. cert = l_cert_new_from_der(der, der_len);
  361. l_free(der);
  362. if (!cert)
  363. goto error;
  364. if (!list)
  365. list = l_queue_new();
  366. l_queue_push_tail(list, cert);
  367. }
  368. return list;
  369. error:
  370. l_queue_destroy(list, (l_queue_destroy_func_t) l_cert_free);
  371. return NULL;
  372. }
  373. LIB_EXPORT struct l_queue *l_pem_load_certificate_list(const char *filename)
  374. {
  375. struct pem_file_info file;
  376. struct l_queue *list = NULL;
  377. if (unlikely(!filename))
  378. return NULL;
  379. if (pem_file_open(&file, filename) < 0)
  380. return NULL;
  381. list = l_pem_load_certificate_list_from_data(file.data,
  382. file.st.st_size);
  383. pem_file_close(&file);
  384. return list;
  385. }
  386. #define SKIP_WHITESPACE(str) \
  387. while (l_ascii_isspace(*(str))) \
  388. (str)++;
  389. static const char *parse_rfc1421_dek_info(char *headers,
  390. const char **out_params)
  391. {
  392. const char *proc_type = NULL;
  393. char *dek_info = NULL;
  394. char *comma;
  395. while (headers) {
  396. char *lf = strchrnul(headers, '\n');
  397. char *key;
  398. key = headers;
  399. SKIP_WHITESPACE(key);
  400. headers = (*lf == '\n') ? lf + 1 : NULL;
  401. if (!memcmp(key, "X-", 2))
  402. key += 2;
  403. if (!memcmp(key, "Proc-Type:", 10)) {
  404. if (proc_type)
  405. return NULL;
  406. proc_type = key + 10;
  407. SKIP_WHITESPACE(proc_type);
  408. } else if (!memcmp(key, "DEK-Info:", 9)) {
  409. if (dek_info)
  410. return NULL;
  411. dek_info = key + 9;
  412. SKIP_WHITESPACE(dek_info);
  413. } else
  414. continue;
  415. while (l_ascii_isspace(lf[-1]))
  416. lf--;
  417. *lf = '\0';
  418. }
  419. if (!proc_type || !dek_info)
  420. return NULL;
  421. /* Skip the version field (should be 3 or 4) */
  422. proc_type = strchr(proc_type, ',');
  423. if (!proc_type)
  424. return NULL;
  425. proc_type++;
  426. SKIP_WHITESPACE(proc_type);
  427. /* Section 4.6.1.1 */
  428. if (strcmp(proc_type, "ENCRYPTED"))
  429. return NULL;
  430. comma = strchr(dek_info, ',');
  431. if (comma) {
  432. *out_params = comma + 1;
  433. SKIP_WHITESPACE(*out_params);
  434. while (comma > dek_info && l_ascii_isspace(comma[-1]))
  435. comma--;
  436. *comma = '\0';
  437. } else
  438. *out_params = NULL;
  439. return dek_info;
  440. }
  441. static struct l_cipher *cipher_from_dek_info(const char *algid, const char *params,
  442. const char *passphrase,
  443. size_t *block_len)
  444. {
  445. enum l_cipher_type type;
  446. struct l_cipher *cipher;
  447. struct l_checksum *md5;
  448. uint8_t key[32];
  449. size_t key_len;
  450. bool ok;
  451. L_AUTO_FREE_VAR(uint8_t *, iv) = NULL;
  452. size_t iv_len;
  453. if (!strcmp(algid, "DES-CBC")) {
  454. type = L_CIPHER_DES_CBC;
  455. key_len = 8;
  456. iv_len = 8;
  457. } else if (!strcmp(algid, "DES-EDE3-CBC")) {
  458. type = L_CIPHER_DES3_EDE_CBC;
  459. key_len = 24;
  460. iv_len = 8;
  461. } else if (!strcmp(algid, "AES-128-CBC")) {
  462. type = L_CIPHER_AES_CBC;
  463. key_len = 16;
  464. iv_len = 16;
  465. } else if (!strcmp(algid, "AES-192-CBC")) {
  466. type = L_CIPHER_AES_CBC;
  467. key_len = 24;
  468. iv_len = 16;
  469. } else if (!strcmp(algid, "AES-256-CBC")) {
  470. type = L_CIPHER_AES_CBC;
  471. key_len = 32;
  472. iv_len = 16;
  473. } else
  474. return NULL;
  475. if (!params || strlen(params) != 2 * iv_len)
  476. return NULL;
  477. *block_len = iv_len;
  478. iv = l_util_from_hexstring(params, &iv_len);
  479. if (!iv)
  480. return NULL;
  481. /*
  482. * The encryption key is the MD5(password | IV[:8]), this comes from
  483. * opessl's crypto/evp/evp_key.c:EVP_BytesToKey() and doesn't seem to
  484. * be backed by any standard:
  485. * https://web.archive.org/web/20190528100132/https://latacora.singles/2018/08/03/the-default-openssh.html
  486. */
  487. md5 = l_checksum_new(L_CHECKSUM_MD5);
  488. if (!md5)
  489. return NULL;
  490. ok = l_checksum_update(md5, passphrase, strlen(passphrase)) &&
  491. l_checksum_update(md5, iv, 8) &&
  492. l_checksum_get_digest(md5, key, 16) == 16;
  493. if (ok && key_len > 16) {
  494. l_checksum_reset(md5);
  495. ok = l_checksum_update(md5, key, 16) &&
  496. l_checksum_update(md5, passphrase, strlen(passphrase)) &&
  497. l_checksum_update(md5, iv, 8) &&
  498. l_checksum_get_digest(md5, key + 16, 16) == 16;
  499. }
  500. l_checksum_free(md5);
  501. if (!ok) {
  502. cipher = NULL;
  503. goto cleanup;
  504. }
  505. cipher = l_cipher_new(type, key, key_len);
  506. if (!cipher)
  507. goto cleanup;
  508. if (l_cipher_set_iv(cipher, iv, iv_len))
  509. goto cleanup;
  510. l_cipher_free(cipher);
  511. cipher = NULL;
  512. cleanup:
  513. explicit_bzero(key, sizeof(key));
  514. return cipher;
  515. }
  516. struct l_key *pem_load_private_key(uint8_t *content, size_t len, char *label,
  517. const char *passphrase, char *headers,
  518. bool *encrypted)
  519. {
  520. struct l_key *pkey;
  521. /*
  522. * RFC7468 Section 10-compatible unencrypted private key label
  523. * (also mentioned in PKCS#8/RFC5958 Section 5), encodes
  524. * the PKCS#8/RFC5958 PrivateKeyInfo structure -- supported
  525. * directly by the pkcs8-key-parser kernel module.
  526. */
  527. if (!strcmp(label, "PRIVATE KEY")) {
  528. /* RFC822 Headers explicitly disallowed in RFC7468 */
  529. if (headers)
  530. goto err;
  531. pkey = cert_key_from_pkcs8_private_key_info(content, len);
  532. goto done;
  533. }
  534. /*
  535. * RFC7468 Section 11-compatible encrypted private key label
  536. * (also mentioned in PKCS#8/RFC5958 Section 5), encodes
  537. * the PKCS#8/RFC5958 EncryptedPrivateKeyInfo structure. We
  538. * decrypt it into a plain PrivateKeyInfo for the
  539. * pkcs8-key-parser module.
  540. */
  541. if (!strcmp(label, "ENCRYPTED PRIVATE KEY")) {
  542. if (encrypted)
  543. *encrypted = true;
  544. if (!passphrase)
  545. goto err;
  546. /* RFC822 Headers explicitly disallowed in RFC7468 */
  547. if (headers)
  548. goto err;
  549. pkey = cert_key_from_pkcs8_encrypted_private_key_info(content,
  550. len,
  551. passphrase);
  552. goto done;
  553. }
  554. /*
  555. * Legacy RSA private key label aka. SSLeay format, understood by
  556. * most software but not documented in an RFC. Encodes the
  557. * PKCS#1/RFC8017 RSAPrivateKey structure. We wrap it in a PKCS#8
  558. * PrivateKeyInfo for the pkcs8-key-parser module.
  559. */
  560. if (!strcmp(label, "RSA PRIVATE KEY")) {
  561. const char *dekalgid;
  562. const char *dekparameters;
  563. /*
  564. * "openssl rsa ..." can produce encrypted PKCS#1-formatted
  565. * keys. These are incompatible with RFC7468 parsing because
  566. * of the RFC822 headers present but the format is the same
  567. * as documented in RFC1421. The encryption algorithms are
  568. * supposed to be the ones defined in RFC1423 but that would
  569. * be only DES-CBC while openssl allows other algorithms.
  570. * When decrypted we get the RSAPrivateKey struct and proceed
  571. * like with the unencrypted format.
  572. */
  573. dekalgid = parse_rfc1421_dek_info(headers, &dekparameters);
  574. if (dekalgid) {
  575. struct l_cipher *alg;
  576. bool r;
  577. size_t block_len;
  578. uint8_t pad;
  579. if (encrypted)
  580. *encrypted = true;
  581. if (!passphrase)
  582. goto err;
  583. alg = cipher_from_dek_info(dekalgid, dekparameters,
  584. passphrase, &block_len);
  585. if (!alg)
  586. goto err;
  587. if (len % block_len || !len) {
  588. l_cipher_free(alg);
  589. goto err;
  590. }
  591. r = l_cipher_decrypt(alg, content, content, len);
  592. l_cipher_free(alg);
  593. if (!r)
  594. goto err;
  595. /* Remove padding like in RFC1423 Section 1.1 */
  596. pad = content[len - 1];
  597. if (pad > block_len || pad == 0)
  598. goto err;
  599. if (!l_secure_memeq(content + len - pad, pad - 1U, pad))
  600. goto err;
  601. len -= pad;
  602. }
  603. pkey = cert_key_from_pkcs1_rsa_private_key(content, len);
  604. goto done;
  605. }
  606. /* Label not known */
  607. err:
  608. pkey = NULL;
  609. done:
  610. explicit_bzero(content, len);
  611. l_free(content);
  612. l_free(label);
  613. l_free(headers);
  614. return pkey;
  615. }
  616. LIB_EXPORT struct l_key *l_pem_load_private_key_from_data(const void *buf,
  617. size_t buf_len,
  618. const char *passphrase,
  619. bool *encrypted)
  620. {
  621. uint8_t *content;
  622. char *label;
  623. size_t len;
  624. char *headers;
  625. if (encrypted)
  626. *encrypted = false;
  627. content = pem_load_buffer(buf, buf_len, &label, &len, &headers, NULL);
  628. if (!content)
  629. return NULL;
  630. return pem_load_private_key(content, len, label, passphrase, headers,
  631. encrypted);
  632. }
  633. /**
  634. * l_pem_load_private_key
  635. * @filename: path string to the PEM file to load
  636. * @passphrase: private key encryption passphrase or NULL for unencrypted
  637. * @encrypted: receives indication whether the file was encrypted if non-NULL
  638. *
  639. * Load the PEM encoded RSA Private Key file at @filename. If it is an
  640. * encrypted private key and @passphrase was non-NULL, the file is
  641. * decrypted. If it's unencrypted @passphrase is ignored. @encrypted
  642. * stores information of whether the file was encrypted, both in a
  643. * success case and on error when NULL is returned. This can be used to
  644. * check if a passphrase is required without prior information.
  645. *
  646. * The passphrase, if given, must have been validated as UTF-8 unless the
  647. * caller knows that PKCS#12 encryption algorithms are not used.
  648. * Use l_utf8_validate.
  649. *
  650. * Returns: An l_key object to be freed with an l_key_free* function,
  651. * or NULL.
  652. **/
  653. LIB_EXPORT struct l_key *l_pem_load_private_key(const char *filename,
  654. const char *passphrase,
  655. bool *encrypted)
  656. {
  657. uint8_t *content;
  658. char *label;
  659. size_t len;
  660. char *headers;
  661. if (encrypted)
  662. *encrypted = false;
  663. content = pem_load_file(filename, &label, &len, &headers);
  664. if (!content)
  665. return NULL;
  666. return pem_load_private_key(content, len, label, passphrase, headers,
  667. encrypted);
  668. }