| 
									
										
										
										
											2020-03-11 06:05:09 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2021-04-22 21:38:44 +08:00
										 |  |  |  * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2020-03-11 06:05:09 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include "apps.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * X509_ctrl_str() is sorely lacking in libcrypto, but is still needed to | 
					
						
							|  |  |  |  * allow the application to process verification options in a manner similar | 
					
						
							|  |  |  |  * to signature or other options that pass through EVP_PKEY_CTX_ctrl_str(), | 
					
						
							|  |  |  |  * for uniformity. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * As soon as more stuff is added, the code will need serious rework.  For | 
					
						
							|  |  |  |  * the moment, it only handles the FIPS 196 / SM2 distinguishing ID. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #ifdef EVP_PKEY_CTRL_SET1_ID
 | 
					
						
							|  |  |  | static ASN1_OCTET_STRING *mk_octet_string(void *value, size_t value_n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ASN1_OCTET_STRING *v = ASN1_OCTET_STRING_new(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (v == NULL) { | 
					
						
							|  |  |  |         BIO_printf(bio_err, "error: allocation failed\n"); | 
					
						
							| 
									
										
										
										
											2021-04-12 11:58:14 +08:00
										 |  |  |     } else if (!ASN1_OCTET_STRING_set(v, value, (int)value_n)) { | 
					
						
							| 
									
										
										
										
											2020-03-11 06:05:09 +08:00
										 |  |  |         ASN1_OCTET_STRING_free(v); | 
					
						
							|  |  |  |         v = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int x509_ctrl(void *object, int cmd, void *value, size_t value_n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (cmd) { | 
					
						
							|  |  |  | #ifdef EVP_PKEY_CTRL_SET1_ID
 | 
					
						
							|  |  |  |     case EVP_PKEY_CTRL_SET1_ID: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ASN1_OCTET_STRING *v = mk_octet_string(value, value_n); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (v == NULL) { | 
					
						
							|  |  |  |                 BIO_printf(bio_err, | 
					
						
							|  |  |  |                            "error: setting distinguishing ID in certificate failed\n"); | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             X509_set0_distinguishing_id(object, v); | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return -2;     /* typical EVP_PKEY return for "unsupported" */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int x509_req_ctrl(void *object, int cmd, void *value, size_t value_n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (cmd) { | 
					
						
							|  |  |  | #ifdef EVP_PKEY_CTRL_SET1_ID
 | 
					
						
							|  |  |  |     case EVP_PKEY_CTRL_SET1_ID: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ASN1_OCTET_STRING *v = mk_octet_string(value, value_n); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (v == NULL) { | 
					
						
							|  |  |  |                 BIO_printf(bio_err, | 
					
						
							|  |  |  |                            "error: setting distinguishing ID in certificate signing request failed\n"); | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             X509_REQ_set0_distinguishing_id(object, v); | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return -2;     /* typical EVP_PKEY return for "unsupported" */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int do_x509_ctrl_string(int (*ctrl)(void *object, int cmd, | 
					
						
							|  |  |  |                                            void *value, size_t value_n), | 
					
						
							|  |  |  |                                void *object, const char *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int rv = 0; | 
					
						
							|  |  |  |     char *stmp, *vtmp = NULL; | 
					
						
							|  |  |  |     size_t vtmp_len = 0; | 
					
						
							|  |  |  |     int cmd = 0; /* Will get command values that make sense somehow */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stmp = OPENSSL_strdup(value); | 
					
						
							|  |  |  |     if (stmp == NULL) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     vtmp = strchr(stmp, ':'); | 
					
						
							|  |  |  |     if (vtmp != NULL) { | 
					
						
							|  |  |  |         *vtmp = 0; | 
					
						
							|  |  |  |         vtmp++; | 
					
						
							|  |  |  |         vtmp_len = strlen(vtmp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (strcmp(stmp, "distid") == 0) { | 
					
						
							|  |  |  | #ifdef EVP_PKEY_CTRL_SET1_ID
 | 
					
						
							|  |  |  |         cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     } else if (strcmp(stmp, "hexdistid") == 0) { | 
					
						
							| 
									
										
										
										
											2020-04-27 07:13:46 +08:00
										 |  |  |         if (vtmp != NULL) { | 
					
						
							|  |  |  |             void *hexid; | 
					
						
							|  |  |  |             long hexid_len = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             hexid = OPENSSL_hexstr2buf((const char *)vtmp, &hexid_len); | 
					
						
							|  |  |  |             OPENSSL_free(stmp); | 
					
						
							|  |  |  |             stmp = vtmp = hexid; | 
					
						
							|  |  |  |             vtmp_len = (size_t)hexid_len; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-03-11 06:05:09 +08:00
										 |  |  | #ifdef EVP_PKEY_CTRL_SET1_ID
 | 
					
						
							|  |  |  |         cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rv = ctrl(object, cmd, vtmp, vtmp_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     OPENSSL_free(stmp); | 
					
						
							|  |  |  |     return rv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int x509_ctrl_string(X509 *x, const char *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return do_x509_ctrl_string(x509_ctrl, x, value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int x509_req_ctrl_string(X509_REQ *x, const char *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return do_x509_ctrl_string(x509_req_ctrl, x, value); | 
					
						
							|  |  |  | } |