1 /* smime-qry.c  -  Get string representations of various certificate parameters
2  *
3  * Copyright (c) 1999 Sampo Kellomaki <sampo@iki.fi>, All Rights Reserved.
4  * License: This software may be distributed under the same license
5  *          terms as openssl (i.e. free, but mandatory attribution).
6  *
7  * 27.9.1999, Created. --Sampo
8  * 30.9.1999, added PKCS12 stuff, --Sampo
9  * 1.10.1999, improved error reporting, --Sampo
10  * 6.10.1999, forked from keygen.c --Sampo
11  * 9.10.1999, reviewed for double frees --Sampo
12  * 18.10.1999, fixed 256 limit in calls to X509_NAME_oneline() --Sampo
13  */
14 
15 #include "platform.h"
16 
17 #include <stdio.h>
18 #include <string.h>
19 #include <time.h>
20 
21 #ifdef __MWERKS__
22 # include "macglue.h"
23 #endif
24 
25 #include <openssl/crypto.h>
26 #include <openssl/buffer.h>
27 #include <openssl/err.h>
28 #include <openssl/rand.h>
29 #include <openssl/conf.h>
30 #include <openssl/bio.h>
31 #include <openssl/stack.h>
32 #include <openssl/objects.h>
33 #include <openssl/asn1.h>
34 #include <openssl/pem.h>
35 #include <openssl/evp.h>
36 #include <openssl/x509.h>
37 #include <openssl/x509v3.h>
38 #include <openssl/pkcs12.h>
39 
40 #define SMIME_INTERNALS  /* we want also our internal helper functions */
41 #include "smimeutil.h"
42 
43 /* ----------------------- get info ----------------------- */
44 
45 /* Obtain some human readable descriptions of the certificate. This is
46  * important, for example, to verify if two certificates have the same
47  * public key modulus.
48  */
49 
50 /* Called by:  smime_get_cert_info */
51 long  /* return serial number, -1 on failure */
get_cert_info(X509 * x509,char ** modulus,char ** fingerprint)52 get_cert_info(X509* x509,
53 		    char** modulus,      /* public key modulus */
54 		    char** fingerprint)  /* finger print that identifies */
55 {
56   BIO* wbio = NULL;
57   if (modulus) *modulus = NULL;
58   if (fingerprint) *fingerprint = NULL;
59   if (!x509) GOTO_ERR("NULL arg");
60 
61   /* Extract the public key part to be printed on paper */
62 
63   if (modulus) {
64     EVP_PKEY* pubkey;
65     if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
66 
67     pubkey = X509_get_pubkey(x509);
68     BN_print(wbio,pubkey->pkey.rsa->n);
69     if (get_written_BIO_data(wbio, modulus) == -1) goto err;
70     BIO_free_all(wbio);
71     wbio = NULL;
72   }
73 
74   /* Extract conventional message digest */
75 
76   if (fingerprint) {
77     unsigned int  md_size;
78     unsigned char md[EVP_MAX_MD_SIZE];
79     if (!X509_digest(x509,EVP_md5(),md,&md_size)) GOTO_ERR("X509_digest");
80     if (!md_size) goto err;
81     if (!(*fingerprint = smime_dotted_hex((char*)md,md_size))) goto err;
82   }
83   return ASN1_INTEGER_get(x509->cert_info->serialNumber);
84 err:
85   if (wbio) BIO_free_all(wbio);
86   return -1;
87 }
88 
89 /* Called by:  main */
90 long  /* return serial number, -1 on failure */
smime_get_cert_info(const char * x509_cert_pem,char ** modulus,char ** fingerprint)91 smime_get_cert_info(const char* x509_cert_pem,
92 		    char** modulus,      /* public key modulus */
93 		    char** fingerprint)  /* finger print that identifies */
94 {
95   long serial = -1;
96   X509* x509 = NULL;
97   if (modulus) *modulus = NULL;
98   if (fingerprint) *fingerprint = NULL;
99   if (!(x509 = extract_certificate(x509_cert_pem))) goto err;
100   serial = get_cert_info(x509, modulus, fingerprint);
101 
102 err:
103   if (x509) X509_free(x509);
104   return serial;
105 }
106 
107 /* -------------------------------------- */
108 
109 /* Called by:  get_req_hash, smime_get_req_modulus */
110 char* /* public key modulus */
get_req_modulus(X509_REQ * req)111 get_req_modulus(X509_REQ* req)
112 {
113   char* modulus = NULL;
114   BIO* wbio = NULL;
115   EVP_PKEY* pubkey;
116 
117   if (!req) GOTO_ERR("NULL arg");
118   if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
119 
120   /* Extract the public key part to be printed on paper */
121 
122   pubkey = X509_REQ_get_pubkey(req);
123   BN_print(wbio,pubkey->pkey.rsa->n);
124   if (get_written_BIO_data(wbio, &modulus) == -1) goto err;
125   BIO_free_all(wbio);
126   return modulus;
127 
128 err:
129   if (wbio) BIO_free_all(wbio);
130   return NULL;
131 }
132 
133 /* Called by:  main */
134 char* /* public key modulus */
smime_get_req_modulus(const char * request_pem)135 smime_get_req_modulus(const char* request_pem)
136 {
137   char* modulus = NULL;
138   X509_REQ* req = NULL;;
139   if (!(req = extract_request(request_pem))) goto err;
140   modulus = get_req_modulus(req);
141 
142 err:
143   if (req) X509_REQ_free(req);
144   return modulus;
145 }
146 
147 /* -------------------------------------- */
148 
149 /* Calculate a hash over any string (I use it for modulus) */
150 
151 /* Called by:  main x2 */
152 char*  /* returns the md5 hash as hex dump */
smime_md5(const char * data)153 smime_md5(const char* data)
154 {
155   EVP_MD_CTX ctx;
156   unsigned int  md_size;
157   unsigned char md[EVP_MAX_MD_SIZE];
158 
159   EVP_DigestInit(&ctx,EVP_md5());
160   EVP_DigestUpdate(&ctx,data,strlen(data));
161   EVP_DigestFinal(&ctx,md,&md_size);
162   return smime_hex((char*)md, md_size);
163 }
164 
165 /* ---------- req hash ----------- */
166 
167 /* request hash is a 25 bit hash used for fast (but not necessarily
168  * collision free) identification and database queries. It has so few
169  * bits because it must fit on coarse 3 of 9 bar code. Basically
170  * 25 bits are encoded in 5 characters from alphabet of 32.
171 
172 Hashing scheme:
173   MD5(subject_DN . attributes . public_key_modulus) --> produces
174   128 bits (16 bytes). Take first three bytes plus LSB of fourth
175   byte and encode them in base 32.
176 
177   On second thought, if we use two bar codes of 13+2 characters, we can
178   represent full 128 bits of information. This should be considered
179   sufficient even on security grounds. So, take 128 bit MD5 hash, divide
180   it in two blocks of 64 bits (8 bytes). Now, 13*5 = 65, so it takes
181   13 characters to encode each block. Last bit is padded with zero.
182 
183 Base 32 encoding:
184   work from LSB to MSB and left to right in groups of 5 bits (5 groups),
185   encode each 5 bit number using
186 
187                      1         2         3
188            01234567890123456789012345678901
189   key ==> "ZY234.6789ABCDEFGHWJKLMNXPQR-TUV" <==
190 
191 
192   Note: Difficult-to-distinguish characters in the sequence have
193         been replaced by less ambiguous ones: 0O1I5S --> ZXYW.-
194 
195   Note: LSB of first 5 bit number is LSB of byte 0. LSB of second 5 bit
196   number is bit 5 of byte 0 and MSB of second number is bit 1 of byte 1.
197 
198   <-- MSB  LSB -->
199 
200 Char                                                                       Pad
201  |   byte 0   byte 1   byte 2   byte 3   byte 4   byte 5   byte 6   byte 7   |
202  V   AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG HHHHHHHH V
203  0:     43210
204  1:  210            43
205  2:            43210
206  3:           0            4321
207  4:                    3210     4
208  5:                              43210
209  6:                                   01      423
210  7:                                      43210
211  8:                                                  43210
212  9:                                               210            43
213 10:                                                         43210
214 11:                                                        0            4321
215 12:                                                                 3210     4
216 
217 */
218 
219 static char req_hash_key[] = "ZY234.6789ABCDEFGHWJKLMNXPQR-TUV";
220 
221 /* Called by:  get_req_hash x2 */
222 static void
encode_64bits(unsigned char * md,char * p)223 encode_64bits(unsigned char* md, char*p)
224 {
225   p[0]  = req_hash_key[ md[0] & 0x1f ];
226   p[1]  = req_hash_key[ ((md[0] >> 5) & 0x07) | ((md[1] & 0x03) << 3) ];
227   p[2]  = req_hash_key[ (md[1] >> 2) & 0x1f ];
228   p[3]  = req_hash_key[ ((md[1] >> 7) & 0x01) | ((md[2] & 0x0f) << 1) ];
229   p[4]  = req_hash_key[ ((md[2] >> 4) & 0x0f) | ((md[3] & 0x01) << 4) ];
230   p[5]  = req_hash_key[ (md[3] >> 1) & 0x1f ];
231   p[6]  = req_hash_key[ ((md[3] >> 6) & 0x03) | ((md[4] & 0x07) << 2) ];
232   p[7]  = req_hash_key[ (md[4] >> 3) & 0x1f ];
233   p[8]  = req_hash_key[ md[5] & 0x1f ];
234   p[9]  = req_hash_key[ ((md[5] >> 5) & 0x07) | ((md[6] & 0x03) << 3) ];
235   p[10] = req_hash_key[ (md[6] >> 2) & 0x1f ];
236   p[11] = req_hash_key[ ((md[6] >> 7) & 0x01) | ((md[7] & 0x0f) << 1) ];
237   p[12] = req_hash_key[ ((md[7] >> 4) & 0x0f) /* | bit4 is zero pad */  ];
238   p[13] = '\0';
239 }
240 
241 /* Called by: */
242 char*  /* hash, ready to print, or NULL if error */
get_req_hash(X509_REQ * req)243 get_req_hash(X509_REQ* req)
244 {
245   EVP_MD_CTX ctx;
246   unsigned int  md_size;
247   unsigned char md[EVP_MAX_MD_SIZE];
248   char* p;
249 
250   if (!req) GOTO_ERR("NULL arg");
251 
252   EVP_DigestInit(&ctx,EVP_md5());
253 
254   if (!(p = get_req_name(req))) goto err;
255   EVP_DigestUpdate(&ctx,p,strlen(p));
256   OPENSSL_free(p);
257 
258   if (!(p = get_req_attr(req))) goto err;
259   EVP_DigestUpdate(&ctx,p,strlen(p));
260   OPENSSL_free(p);
261 
262   if (!(p = get_req_modulus(req))) goto err;
263   EVP_DigestUpdate(&ctx,p,strlen(p));
264   OPENSSL_free(p);
265 
266   EVP_DigestFinal(&ctx,md,&md_size);
267 
268   if (md_size < 16) goto err;
269   if (!(p = (char*)OPENSSL_malloc(13+13+1))) GOTO_ERR("no memory?");
270 
271   encode_64bits(md, p);       /* block 1, first 13 chars */
272   encode_64bits(md+8, p+13);  /* block 2, second 13 chars */
273   return p;
274 
275 err:
276   return NULL;
277 }
278 
279 char* /* 25 bit hash as string like `*Z4K67W*' or NULL if error */
smime_get_req_hash(const char * request_pem)280 smime_get_req_hash(const char* request_pem)
281 {
282   char* n = NULL;
283   X509_REQ* req = NULL;
284   if (!(req = extract_request(request_pem))) goto err;
285   n = get_req_hash(req);
286 
287 err:
288   if (req) X509_REQ_free(req);
289   return n;
290 }
291 
292 /* -------------------------------------- */
293 
294 /* Get distinguished name information from the certificate */
295 
296 /* Called by:  smime_get_cert_names */
297 long  /* return serial number, -1 on failure */
get_cert_names(X509 * x509,char ** subject_DN,char ** issuer_DN)298 get_cert_names(X509* x509,
299 	       char** subject_DN,   /* who the certificate belongs to */
300 	       char** issuer_DN)    /* who signed the certificate */
301 {
302   long serial = -1;
303 
304   if (subject_DN) *subject_DN = NULL;
305   if (issuer_DN) *issuer_DN = NULL;
306   if (!x509) GOTO_ERR("NULL arg");
307 
308   if (subject_DN) {  /* if you don't want to know subject, pass this as NULL */
309     if (!(*subject_DN = X509_NAME_oneline(X509_get_subject_name(x509),NULL,0)))
310       GOTO_ERR("no memory?");
311   }
312 
313   if (issuer_DN) {   /* if you don't want to know issuer, pass NULL here */
314     if (!(*issuer_DN = X509_NAME_oneline(X509_get_issuer_name(x509),NULL,0)))
315       GOTO_ERR("no memory?");
316   }
317 
318   /* extract serial number */
319 
320   serial = ASN1_INTEGER_get(x509->cert_info->serialNumber);
321 err:
322   return serial;
323 }
324 
325 /* Called by:  main */
326 long  /* return serial number, -1 on failure */
smime_get_cert_names(const char * x509_cert_pem,char ** subject_DN,char ** issuer_DN)327 smime_get_cert_names(const char* x509_cert_pem,
328 		     char** subject_DN,   /* who the certificate belongs to */
329 		     char** issuer_DN)    /* who signed the certificate */
330 {
331   long serial = -1;
332   X509* x509 = NULL;
333   if (subject_DN) *subject_DN = NULL;
334   if (issuer_DN) *issuer_DN = NULL;
335   if (!(x509 = extract_certificate(x509_cert_pem))) goto err;
336   serial = get_cert_names(x509, subject_DN, issuer_DN);
337 
338 err:
339   if (x509) X509_free(x509);
340   return serial;
341 }
342 
343 /* -------------------------------------- */
344 
345 /* Getting the attributes does not appear to be too well supported, i.e.
346  * there is no easy way. You just have to walk the data structure yourself.
347  * This function only understands sets of one value and single values.
348  * See crypto/asn1/asn1_par.c for similar code. */
349 
350 /* Called by:  get_req_hash, smime_get_req_attr */
351 char* /* new line separated list of attribute value pairs */
get_req_attr(X509_REQ * req)352 get_req_attr(X509_REQ* req)
353 {
354   int i;
355   STACK_OF(X509_ATTRIBUTE)* xas = NULL;
356   X509_ATTRIBUTE* xa;
357   ASN1_TYPE* val;
358   STACK_OF(ASN1_TYPE)* vals = NULL;
359   char* buf = NULL;
360 
361   if (!req) GOTO_ERR("NULL arg");
362   if (!(buf = strdup(""))) GOTO_ERR("no memory?");
363   if ((xas = req->req_info->attributes) == NULL) goto err; /* no attributes */
364 
365   for (i = 0; i < sk_X509_ATTRIBUTE_num(xas); i++) {
366     xa = sk_X509_ATTRIBUTE_value(xas, i);
367 
368     /* print the (long)name of the attribute */
369 
370     if (!(buf = concat(buf, OBJ_nid2ln(OBJ_obj2nid(xa->object))))) goto err;
371     if (!(buf = concat(buf, "="))) goto err;
372 
373     /* Obtain either the single value or the first value in the set */
374 
375     if (1 /*|| xa->single  **** this is called set on some versions */) {
376       if ((vals = xa->value.set) && sk_ASN1_TYPE_num(vals)) {
377 	val = sk_ASN1_TYPE_value(vals,0);
378       } else
379 	val = NULL;
380     } else {
381       val = xa->value.single;
382     }
383     if (val) {
384       /* print the value. *** for now this only works for various string
385          types */
386       if (!(buf = concatmem(buf, (char*)(val->value.asn1_string->data),
387 			    val->value.asn1_string->length))) goto err;
388     }
389 
390     if (!(buf = concat(buf,"\n"))) goto err;
391   }
392   return buf;
393 err:
394   return NULL;
395 }
396 
397 /* Called by:  main */
398 char* /* public key modulus */
smime_get_req_attr(const char * request_pem)399 smime_get_req_attr(const char* request_pem)
400 {
401   char* name = NULL;
402   X509_REQ* req = NULL;
403   if (!(req = extract_request(request_pem))) goto err;
404   name = get_req_attr(req);
405 
406 err:
407   if (req) X509_REQ_free(req);
408   return name;
409 }
410 
411 /* Called by:  get_req_hash, smime_get_req_name */
412 char* /* subject_DN - who the request belongs to */
get_req_name(X509_REQ * req)413 get_req_name(X509_REQ* req)
414 {
415   if (!req) GOTO_ERR("NULL arg");
416   return X509_NAME_oneline(X509_REQ_get_subject_name(req),NULL,0);
417 err:
418   return NULL;
419 }
420 
421 /* Called by:  main */
422 char* /* public key modulus */
smime_get_req_name(const char * request_pem)423 smime_get_req_name(const char* request_pem)
424 {
425   char* name = NULL;
426   X509_REQ* req = NULL;
427   if (!(req = extract_request(request_pem))) goto err;
428   name = get_req_name(req);
429 
430 err:
431   if (req) X509_REQ_free(req);
432   return name;
433 }
434 
435 /* EOF  -  smime-qry.c */
436