cmp_status.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
  3. * Copyright Nokia 2007-2019
  4. * Copyright Siemens AG 2015-2019
  5. *
  6. * Licensed under the Apache License 2.0 (the "License"). You may not use
  7. * this file except in compliance with the License. You can obtain a copy
  8. * in the file LICENSE in the source distribution or at
  9. * https://www.openssl.org/source/license.html
  10. */
  11. /* CMP functions for PKIStatusInfo handling and PKIMessage decomposition */
  12. #include <string.h>
  13. #include "cmp_local.h"
  14. /* explicit #includes not strictly needed since implied by the above: */
  15. #include <time.h>
  16. #include <openssl/cmp.h>
  17. #include <openssl/crmf.h>
  18. #include <openssl/err.h> /* needed in case config no-deprecated */
  19. #include <openssl/engine.h>
  20. #include <openssl/evp.h>
  21. #include <openssl/objects.h>
  22. #include <openssl/x509.h>
  23. #include <openssl/asn1err.h> /* for ASN1_R_TOO_SMALL and ASN1_R_TOO_LARGE */
  24. /* CMP functions related to PKIStatus */
  25. int ossl_cmp_pkisi_get_pkistatus(const OSSL_CMP_PKISI *si)
  26. {
  27. if (!ossl_assert(si != NULL && si->status != NULL))
  28. return -1;
  29. return ossl_cmp_asn1_get_int(si->status);
  30. }
  31. /*
  32. * return the declared identifier and a short explanation for the PKIStatus
  33. * value as specified in RFC4210, Appendix F.
  34. */
  35. const char *ossl_cmp_PKIStatus_to_string(int status)
  36. {
  37. switch (status) {
  38. case OSSL_CMP_PKISTATUS_accepted:
  39. return "PKIStatus: accepted";
  40. case OSSL_CMP_PKISTATUS_grantedWithMods:
  41. return "PKIStatus: granted with modifications";
  42. case OSSL_CMP_PKISTATUS_rejection:
  43. return "PKIStatus: rejection";
  44. case OSSL_CMP_PKISTATUS_waiting:
  45. return "PKIStatus: waiting";
  46. case OSSL_CMP_PKISTATUS_revocationWarning:
  47. return "PKIStatus: revocation warning - a revocation of the cert is imminent";
  48. case OSSL_CMP_PKISTATUS_revocationNotification:
  49. return "PKIStatus: revocation notification - a revocation of the cert has occurred";
  50. case OSSL_CMP_PKISTATUS_keyUpdateWarning:
  51. return "PKIStatus: key update warning - update already done for the cert";
  52. default:
  53. {
  54. char buf[40];
  55. BIO_snprintf(buf, sizeof(buf), "PKIStatus: invalid=%d", status);
  56. CMPerr(0, CMP_R_ERROR_PARSING_PKISTATUS);
  57. ossl_cmp_add_error_data(buf);
  58. return NULL;
  59. }
  60. }
  61. }
  62. /*
  63. * returns a pointer to the statusString contained in a PKIStatusInfo
  64. * returns NULL on error
  65. */
  66. OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusstring(const OSSL_CMP_PKISI *si)
  67. {
  68. if (!ossl_assert(si != NULL))
  69. return NULL;
  70. return si->statusString;
  71. }
  72. /*
  73. * returns the FailureInfo bits of the given PKIStatusInfo
  74. * returns -1 on error
  75. */
  76. int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si)
  77. {
  78. int i;
  79. int res = 0;
  80. if (!ossl_assert(si != NULL && si->failInfo != NULL))
  81. return -1;
  82. for (i = 0; i <= OSSL_CMP_PKIFAILUREINFO_MAX; i++)
  83. if (ASN1_BIT_STRING_get_bit(si->failInfo, i))
  84. res |= 1 << i;
  85. return res;
  86. }
  87. /*
  88. * internal function
  89. * convert PKIFailureInfo number to human-readable string
  90. *
  91. * returns pointer to static string
  92. * returns NULL on error
  93. */
  94. static const char *CMP_PKIFAILUREINFO_to_string(int number)
  95. {
  96. switch (number) {
  97. case OSSL_CMP_PKIFAILUREINFO_badAlg:
  98. return "badAlg";
  99. case OSSL_CMP_PKIFAILUREINFO_badMessageCheck:
  100. return "badMessageCheck";
  101. case OSSL_CMP_PKIFAILUREINFO_badRequest:
  102. return "badRequest";
  103. case OSSL_CMP_PKIFAILUREINFO_badTime:
  104. return "badTime";
  105. case OSSL_CMP_PKIFAILUREINFO_badCertId:
  106. return "badCertId";
  107. case OSSL_CMP_PKIFAILUREINFO_badDataFormat:
  108. return "badDataFormat";
  109. case OSSL_CMP_PKIFAILUREINFO_wrongAuthority:
  110. return "wrongAuthority";
  111. case OSSL_CMP_PKIFAILUREINFO_incorrectData:
  112. return "incorrectData";
  113. case OSSL_CMP_PKIFAILUREINFO_missingTimeStamp:
  114. return "missingTimeStamp";
  115. case OSSL_CMP_PKIFAILUREINFO_badPOP:
  116. return "badPOP";
  117. case OSSL_CMP_PKIFAILUREINFO_certRevoked:
  118. return "certRevoked";
  119. case OSSL_CMP_PKIFAILUREINFO_certConfirmed:
  120. return "certConfirmed";
  121. case OSSL_CMP_PKIFAILUREINFO_wrongIntegrity:
  122. return "wrongIntegrity";
  123. case OSSL_CMP_PKIFAILUREINFO_badRecipientNonce:
  124. return "badRecipientNonce";
  125. case OSSL_CMP_PKIFAILUREINFO_timeNotAvailable:
  126. return "timeNotAvailable";
  127. case OSSL_CMP_PKIFAILUREINFO_unacceptedPolicy:
  128. return "unacceptedPolicy";
  129. case OSSL_CMP_PKIFAILUREINFO_unacceptedExtension:
  130. return "unacceptedExtension";
  131. case OSSL_CMP_PKIFAILUREINFO_addInfoNotAvailable:
  132. return "addInfoNotAvailable";
  133. case OSSL_CMP_PKIFAILUREINFO_badSenderNonce:
  134. return "badSenderNonce";
  135. case OSSL_CMP_PKIFAILUREINFO_badCertTemplate:
  136. return "badCertTemplate";
  137. case OSSL_CMP_PKIFAILUREINFO_signerNotTrusted:
  138. return "signerNotTrusted";
  139. case OSSL_CMP_PKIFAILUREINFO_transactionIdInUse:
  140. return "transactionIdInUse";
  141. case OSSL_CMP_PKIFAILUREINFO_unsupportedVersion:
  142. return "unsupportedVersion";
  143. case OSSL_CMP_PKIFAILUREINFO_notAuthorized:
  144. return "notAuthorized";
  145. case OSSL_CMP_PKIFAILUREINFO_systemUnavail:
  146. return "systemUnavail";
  147. case OSSL_CMP_PKIFAILUREINFO_systemFailure:
  148. return "systemFailure";
  149. case OSSL_CMP_PKIFAILUREINFO_duplicateCertReq:
  150. return "duplicateCertReq";
  151. default:
  152. return NULL; /* illegal failure number */
  153. }
  154. }
  155. /*
  156. * checks PKIFailureInfo bits in a given PKIStatusInfo
  157. * returns 1 if a given bit is set, 0 if not, -1 on error
  158. */
  159. int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index)
  160. {
  161. if (!ossl_assert(si != NULL && si->failInfo != NULL))
  162. return -1;
  163. if (bit_index < 0 || bit_index > OSSL_CMP_PKIFAILUREINFO_MAX) {
  164. CMPerr(0, CMP_R_INVALID_ARGS);
  165. return -1;
  166. }
  167. return ASN1_BIT_STRING_get_bit(si->failInfo, bit_index);
  168. }
  169. /*
  170. * place human-readable error string created from PKIStatusInfo in given buffer
  171. * returns pointer to the same buffer containing the string, or NULL on error
  172. */
  173. char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
  174. size_t bufsize)
  175. {
  176. int status, failure, fail_info;
  177. const char *status_string, *failure_string;
  178. OSSL_CMP_PKIFREETEXT *status_strings;
  179. ASN1_UTF8STRING *text;
  180. int i;
  181. int printed_chars;
  182. int failinfo_found = 0;
  183. int n_status_strings;
  184. char* write_ptr = buf;
  185. #define ADVANCE_BUFFER \
  186. if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \
  187. return NULL; \
  188. write_ptr += printed_chars; \
  189. bufsize -= printed_chars;
  190. if (ctx == NULL
  191. || buf == NULL
  192. || (status = OSSL_CMP_CTX_get_status(ctx)) < 0
  193. || (status_string = ossl_cmp_PKIStatus_to_string(status)) == NULL)
  194. return NULL;
  195. printed_chars = BIO_snprintf(write_ptr, bufsize, "%s", status_string);
  196. ADVANCE_BUFFER;
  197. /* failInfo is optional and may be empty */
  198. if ((fail_info = OSSL_CMP_CTX_get_failInfoCode(ctx)) > 0) {
  199. printed_chars = BIO_snprintf(write_ptr, bufsize, "; PKIFailureInfo: ");
  200. ADVANCE_BUFFER;
  201. for (failure = 0; failure <= OSSL_CMP_PKIFAILUREINFO_MAX; failure++) {
  202. if ((fail_info & (1 << failure)) != 0) {
  203. failure_string = CMP_PKIFAILUREINFO_to_string(failure);
  204. if (failure_string != NULL) {
  205. printed_chars = BIO_snprintf(write_ptr, bufsize, "%s%s",
  206. failure > 0 ? ", " : "",
  207. failure_string);
  208. ADVANCE_BUFFER;
  209. failinfo_found = 1;
  210. }
  211. }
  212. }
  213. }
  214. if (!failinfo_found && status != OSSL_CMP_PKISTATUS_accepted
  215. && status != OSSL_CMP_PKISTATUS_grantedWithMods) {
  216. printed_chars = BIO_snprintf(write_ptr, bufsize, "; <no failure info>");
  217. ADVANCE_BUFFER;
  218. }
  219. /* statusString sequence is optional and may be empty */
  220. status_strings = OSSL_CMP_CTX_get0_statusString(ctx);
  221. n_status_strings = sk_ASN1_UTF8STRING_num(status_strings);
  222. if (n_status_strings > 0) {
  223. printed_chars = BIO_snprintf(write_ptr, bufsize, "; StatusString%s: ",
  224. n_status_strings > 1 ? "s" : "");
  225. ADVANCE_BUFFER;
  226. for (i = 0; i < n_status_strings; i++) {
  227. text = sk_ASN1_UTF8STRING_value(status_strings, i);
  228. printed_chars = BIO_snprintf(write_ptr, bufsize, "\"%s\"%s",
  229. ASN1_STRING_get0_data(text),
  230. i < n_status_strings - 1 ? ", " : "");
  231. ADVANCE_BUFFER;
  232. }
  233. }
  234. #undef ADVANCE_BUFFER
  235. return buf;
  236. }
  237. /*
  238. * Creates a new PKIStatusInfo structure and fills it in
  239. * returns a pointer to the structure on success, NULL on error
  240. * note: strongly overlaps with TS_RESP_CTX_set_status_info()
  241. * and TS_RESP_CTX_add_failure_info() in ../ts/ts_rsp_sign.c
  242. */
  243. OSSL_CMP_PKISI *ossl_cmp_statusinfo_new(int status, int fail_info,
  244. const char *text)
  245. {
  246. OSSL_CMP_PKISI *si = OSSL_CMP_PKISI_new();
  247. ASN1_UTF8STRING *utf8_text = NULL;
  248. int failure;
  249. if (si == NULL)
  250. goto err;
  251. if (!ASN1_INTEGER_set(si->status, status))
  252. goto err;
  253. if (text != NULL) {
  254. if ((utf8_text = ASN1_UTF8STRING_new()) == NULL
  255. || !ASN1_STRING_set(utf8_text, text, -1))
  256. goto err;
  257. if ((si->statusString = sk_ASN1_UTF8STRING_new_null()) == NULL)
  258. goto err;
  259. if (!sk_ASN1_UTF8STRING_push(si->statusString, utf8_text))
  260. goto err;
  261. /* Ownership is lost. */
  262. utf8_text = NULL;
  263. }
  264. for (failure = 0; failure <= OSSL_CMP_PKIFAILUREINFO_MAX; failure++) {
  265. if ((fail_info & (1 << failure)) != 0) {
  266. if (si->failInfo == NULL
  267. && (si->failInfo = ASN1_BIT_STRING_new()) == NULL)
  268. goto err;
  269. if (!ASN1_BIT_STRING_set_bit(si->failInfo, failure, 1))
  270. goto err;
  271. }
  272. }
  273. return si;
  274. err:
  275. OSSL_CMP_PKISI_free(si);
  276. ASN1_UTF8STRING_free(utf8_text);
  277. return NULL;
  278. }