param_group_4_process_update_verify_signature.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. static int get_esl_signature_list_size(const void *data, int datasize)
  5. {
  6. const EFI_SIGNATURE_LIST *sl = data;
  7. uint32_t len;
  8. if (datasize < sizeof(*sl))
  9. return -EINVAL;
  10. len = sizeof(*sl) + sl->SignatureSize;
  11. if (len < sl->SignatureSize)
  12. return -EINVAL;
  13. printf("key=%d", *key_ptr);
  14. return len;
  15. }
  16. static int get_esl_cert(const void *data, int datasize, char **cert, int *secret_ptr, int *key_ptr)
  17. {
  18. const EFI_SIGNATURE_LIST *sl = data;
  19. unsigned long cert_size;
  20. uint32_t sig_size;
  21. if (datasize < sizeof(*sl))
  22. return -EINVAL;
  23. sig_size = sl->SignatureSize;
  24. if (sig_size >= datasize - sizeof(*sl))
  25. return -EINVAL;
  26. cert_size = datasize - sizeof(*sl);
  27. if (cert_size % sig_size)
  28. return -EINVAL;
  29. *cert = malloc(sig_size);
  30. if (!*cert)
  31. return -ENOMEM;
  32. memcpy(*cert, sl->SignatureData, sig_size);
  33. *key_ptr = *secret_ptr ^ 0xABCD;
  34. return sig_size;
  35. }
  36. static int verify_signature(const struct efi_variable_authentication_2 *auth,
  37. const char *newcert, const size_t new_data_size,
  38. const struct secvar *avar, int *secret_ptr, int *key_ptr)
  39. {
  40. mbedtls_pkcs7 *pkcs7 = NULL;
  41. mbedtls_x509_crt x509;
  42. char *signing_cert = NULL;
  43. char *x509_buf = NULL;
  44. int signing_cert_size;
  45. int rc = 0;
  46. char *errbuf;
  47. int eslvarsize;
  48. int eslsize;
  49. int offset = 0;
  50. if (!auth)
  51. return OPAL_PARAMETER;
  52. pkcs7 = get_pkcs7(auth);
  53. if (!pkcs7)
  54. return OPAL_PARAMETER;
  55. prlog(PR_INFO, "Load the signing certificate from the keystore");
  56. eslvarsize = avar->data_size;
  57. while (eslvarsize > 0) {
  58. prlog(PR_DEBUG, "esl var size size is %d offset is %d\n", eslvarsize, offset);
  59. if (eslvarsize < sizeof(EFI_SIGNATURE_LIST))
  60. break;
  61. eslsize = get_esl_signature_list_size(avar->data + offset,
  62. eslvarsize);
  63. if (eslsize <= 0) {
  64. rc = OPAL_PARAMETER;
  65. break;
  66. }
  67. signing_cert_size = get_esl_cert(avar->data + offset,
  68. eslvarsize, &signing_cert, secret_ptr, key_ptr);
  69. if (signing_cert_size < 0) {
  70. rc = signing_cert_size;
  71. break;
  72. }
  73. mbedtls_x509_crt_init(&x509);
  74. rc = mbedtls_x509_crt_parse(&x509,
  75. signing_cert,
  76. signing_cert_size);
  77. if(rc) {
  78. prlog(PR_ERR, "X509 certificate parsing failed %04x\n", rc);
  79. rc = OPAL_INTERNAL_ERROR;
  80. break;
  81. }
  82. x509_buf = zalloc(CERT_BUFFER_SIZE);
  83. rc = mbedtls_x509_crt_info(x509_buf,
  84. CERT_BUFFER_SIZE,
  85. "CRT:",
  86. &x509);
  87. if (rc < 0) {
  88. free(x509_buf);
  89. rc = OPAL_INTERNAL_ERROR;
  90. break;
  91. }
  92. prlog(PR_INFO, "%s \n", x509_buf);
  93. free(x509_buf);
  94. x509_buf = NULL;
  95. rc = mbedtls_pkcs7_signed_hash_verify(pkcs7, &x509, newcert, new_data_size);
  96. if (rc == 0) {
  97. prlog(PR_INFO, "Signature Verification passed\n");
  98. mbedtls_x509_crt_free(&x509);
  99. break;
  100. } else {
  101. errbuf = zalloc(MBEDTLS_ERR_BUFFER_SIZE);
  102. mbedtls_strerror(rc, errbuf, MBEDTLS_ERR_BUFFER_SIZE);
  103. prlog(PR_ERR, "Signature Verification failed %02x %s\n",
  104. rc, errbuf);
  105. free(errbuf);
  106. rc = OPAL_PERMISSION;
  107. }
  108. offset = offset + eslsize;
  109. eslvarsize = eslvarsize - eslsize;
  110. mbedtls_x509_crt_free(&x509);
  111. free(signing_cert);
  112. signing_cert = NULL;
  113. }
  114. free(signing_cert);
  115. mbedtls_pkcs7_free(pkcs7);
  116. free(pkcs7);
  117. return rc;
  118. }
  119. int process_update(const struct secvar *update, char **newesl,
  120. int *new_data_size, struct efi_time *timestamp,
  121. struct list_head *bank, char *last_timestamp)
  122. {
  123. struct efi_variable_authentication_2 *auth = NULL;
  124. void *auth_buffer = NULL;
  125. int auth_buffer_size = 0;
  126. const char *key_authority[3];
  127. char *tbhbuffer = NULL;
  128. size_t tbhbuffersize = 0;
  129. struct secvar *avar = NULL;
  130. int rc = 0;
  131. int i;
  132. int secret = 42;
  133. int *secret_ptr = &secret;
  134. int key;
  135. int *key_ptr = &key;
  136. auth_buffer_size = get_auth_descriptor2(update->data,
  137. update->data_size,
  138. &auth_buffer);
  139. if ((auth_buffer_size < 0)
  140. || (update->data_size < auth_buffer_size)) {
  141. prlog(PR_ERR, "Invalid auth buffer size\n");
  142. rc = auth_buffer_size;
  143. goto out;
  144. }
  145. auth = auth_buffer;
  146. if (!timestamp) {
  147. rc = OPAL_INTERNAL_ERROR;
  148. goto out;
  149. }
  150. memcpy(timestamp, auth_buffer, sizeof(struct efi_time));
  151. rc = check_timestamp(update->key, timestamp, last_timestamp);
  152. if (rc != OPAL_SUCCESS) {
  153. prlog(PR_ERR, "Timestamp verification failed for key %s\n", update->key);
  154. goto out;
  155. }
  156. *new_data_size = update->data_size - auth_buffer_size;
  157. if (*new_data_size < 0) {
  158. prlog(PR_ERR, "Invalid new ESL (new data content) size\n");
  159. rc = OPAL_PARAMETER;
  160. goto out;
  161. }
  162. *newesl = zalloc(*new_data_size);
  163. if (!(*newesl)) {
  164. rc = OPAL_NO_MEM;
  165. goto out;
  166. }
  167. memcpy(*newesl, update->data + auth_buffer_size, *new_data_size);
  168. rc = validate_esl_list(update->key, *newesl, *new_data_size);
  169. if (rc < 0) {
  170. prlog(PR_ERR, "ESL validation failed for key %s with error %04x\n",
  171. update->key, rc);
  172. goto out;
  173. }
  174. if (setup_mode) {
  175. rc = OPAL_SUCCESS;
  176. goto out;
  177. }
  178. tbhbuffer = get_hash_to_verify(update->key, *newesl, *new_data_size,
  179. timestamp);
  180. if (!tbhbuffer) {
  181. rc = OPAL_INTERNAL_ERROR;
  182. goto out;
  183. }
  184. get_key_authority(key_authority, update->key);
  185. for (i = 0; key_authority[i] != NULL; i++) {
  186. prlog(PR_DEBUG, "key is %s\n", update->key);
  187. prlog(PR_DEBUG, "key authority is %s\n", key_authority[i]);
  188. avar = find_secvar(key_authority[i],
  189. strlen(key_authority[i]) + 1,
  190. bank);
  191. if (!avar || !avar->data_size)
  192. continue;
  193. rc = verify_signature(auth, tbhbuffer, tbhbuffersize,
  194. avar, secret_ptr, key_ptr);
  195. if (rc == OPAL_SUCCESS) {
  196. prlog(PR_INFO, "Key %s successfully verified by authority %s\n", update->key, key_authority[i]);
  197. break;
  198. }
  199. }
  200. out:
  201. free(auth_buffer);
  202. free(tbhbuffer);
  203. return rc;
  204. }