Fix typo in rsautl.
authorDr. Stephen Henson <steve@openssl.org>
Tue, 5 Sep 2000 22:30:38 +0000 (22:30 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 5 Sep 2000 22:30:38 +0000 (22:30 +0000)
Add support for settable verify time in X509_verify_cert().

Document rsautl utility.

CHANGES
apps/rsautl.c
crypto/x509/x509.h
crypto/x509/x509_vfy.c
crypto/x509/x509_vfy.h
doc/apps/rsautl.pod [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 4fe8ae9..3f0fa4c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,57 +3,61 @@
  _______________
 
  Changes between 0.9.5a and 0.9.6  [xx XXX 2000]
+
+  *) Allow the verify time to be set by an application,
+     rather than always using the current time.
+     [Steve Henson]
   
-   *) Phase 2 verify code reorganisation. The certificate
-      verify code now looks up an issuer certificate by a
-      number of criteria: subject name, authority key id
-      and key usage. It also verifies self signed certificates
-      by the same criteria. The main comparison function is
-      X509_check_issued() which performs these checks.
+  *) Phase 2 verify code reorganisation. The certificate
+     verify code now looks up an issuer certificate by a
+     number of criteria: subject name, authority key id
+     and key usage. It also verifies self signed certificates
+     by the same criteria. The main comparison function is
+     X509_check_issued() which performs these checks.
  
-      Lot of changes were necessary in order to support this
-      without completely rewriting the lookup code.
+     Lot of changes were necessary in order to support this
+     without completely rewriting the lookup code.
  
-      Authority and subject key identifier are now cached.
+     Authority and subject key identifier are now cached.
  
-      The LHASH 'certs' is X509_STORE has now been replaced
-      by a STACK_OF(X509_OBJECT). This is mainly because an
-      LHASH can't store or retrieve multiple objects with
-      the same hash value.
-
-      As a result various functions (which were all internal
-      use only) have changed to handle the new X509_STORE
-      structure. This will break anything that messed round
-      with X509_STORE internally.
+     The LHASH 'certs' is X509_STORE has now been replaced
+     by a STACK_OF(X509_OBJECT). This is mainly because an
+     LHASH can't store or retrieve multiple objects with
+     the same hash value.
+
+     As a result various functions (which were all internal
+     use only) have changed to handle the new X509_STORE
+     structure. This will break anything that messed round
+     with X509_STORE internally.
  
-      The functions X509_STORE_add_cert() now checks for an
-      exact match, rather than just subject name.
+     The functions X509_STORE_add_cert() now checks for an
+     exact match, rather than just subject name.
  
-      The X509_STORE API doesn't directly support the retrieval
-      of multiple certificates matching a given criteria, however
-      this can be worked round by performing a lookup first
-      (which will fill the cache with candidate certificates)
-      and then examining the cache for matches. This is probably
-      the best we can do without throwing out X509_LOOKUP
-      entirely (maybe later...).
+     The X509_STORE API doesn't directly support the retrieval
+     of multiple certificates matching a given criteria, however
+     this can be worked round by performing a lookup first
+     (which will fill the cache with candidate certificates)
+     and then examining the cache for matches. This is probably
+     the best we can do without throwing out X509_LOOKUP
+     entirely (maybe later...).
  
-      The X509_VERIFY_CTX structure has been enhanced considerably.
+     The X509_VERIFY_CTX structure has been enhanced considerably.
  
-      All certificate lookup operations now go via a get_issuer()
-      callback. Although this currently uses an X509_STORE it
-      can be replaced by custom lookups. This is a simple way
-      to bypass the X509_STORE hackery necessary to make this
-      work and makes it possible to use more efficient techniques
-      in future. A very simple version which uses a simple
-      STACK for its trusted certificate store is also provided
-      using X509_STORE_CTX_trusted_stack().
+     All certificate lookup operations now go via a get_issuer()
+     callback. Although this currently uses an X509_STORE it
+     can be replaced by custom lookups. This is a simple way
+     to bypass the X509_STORE hackery necessary to make this
+     work and makes it possible to use more efficient techniques
+     in future. A very simple version which uses a simple
+     STACK for its trusted certificate store is also provided
+     using X509_STORE_CTX_trusted_stack().
  
-      The verify_cb() and verify() callbacks now have equivalents
-      in the X509_STORE_CTX structure.
+     The verify_cb() and verify() callbacks now have equivalents
+     in the X509_STORE_CTX structure.
  
-      X509_STORE_CTX also has a 'flags' field which can be used
-      to customise the verify behaviour.
-      [Steve Henson]
+     X509_STORE_CTX also has a 'flags' field which can be used
+     to customise the verify behaviour.
+     [Steve Henson]
  
   *) Add new PKCS#7 signing option PKCS7_NOSMIMECAP which 
      excludes S/MIME capabilities.
index 3a58b45..f8f68d9 100644 (file)
@@ -141,7 +141,7 @@ int MAIN(int argc, char **argv)
                argv++;
        }
 
-       if(need_priv && (key_type == KEY_PRIVKEY)) {
+       if(need_priv && (key_type != KEY_PRIVKEY)) {
                BIO_printf(bio_err, "A private key is needed for this operation\n");
                goto end;
        }
index db80eda..b95a2ee 100644 (file)
@@ -800,7 +800,9 @@ RSA *RSAPrivateKey_dup(RSA *rsa);
 
 #endif /* !SSLEAY_MACROS */
 
+int            X509_cmp_time(ASN1_TIME *s, time_t *t);
 int            X509_cmp_current_time(ASN1_TIME *s);
+ASN1_TIME *    X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
 ASN1_TIME *    X509_gmtime_adj(ASN1_TIME *s, long adj);
 
 const char *   X509_get_default_cert_area(void );
index 07a8bd4..b8fb24a 100644 (file)
@@ -429,6 +429,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
        int i,ok=0,n;
        X509 *xs,*xi;
        EVP_PKEY *pkey=NULL;
+       time_t *ptime;
        int (*cb)();
 
        cb=ctx->verify_cb;
@@ -438,8 +439,9 @@ static int internal_verify(X509_STORE_CTX *ctx)
        ctx->error_depth=n-1;
        n--;
        xi=sk_X509_value(ctx->chain,n);
-       if (X509_NAME_cmp(X509_get_subject_name(xi),
-               X509_get_issuer_name(xi)) == 0)
+       if(ctx->flags & X509_V_FLAG_USE_CHECK_TIME) ptime = &ctx->check_time;
+       else ptime = NULL;
+       if (ctx->check_issued(ctx, xi, xi))
                xs=xi;
        else
                {
@@ -485,7 +487,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
                        EVP_PKEY_free(pkey);
                        pkey=NULL;
 
-                       i=X509_cmp_current_time(X509_get_notBefore(xs));
+                       i=X509_cmp_time(X509_get_notBefore(xs), ptime);
                        if (i == 0)
                                {
                                ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
@@ -503,7 +505,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
                        xs->valid=1;
                        }
 
-               i=X509_cmp_current_time(X509_get_notAfter(xs));
+               i=X509_cmp_time(X509_get_notAfter(xs), ptime);
                if (i == 0)
                        {
                        ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
@@ -540,6 +542,11 @@ end:
        }
 
 int X509_cmp_current_time(ASN1_TIME *ctm)
+{
+       return X509_cmp_time(ctm, NULL);
+}
+
+int X509_cmp_time(ASN1_TIME *ctm, time_t *cmp_time)
        {
        char *str;
        ASN1_TIME atm;
@@ -594,7 +601,7 @@ int X509_cmp_current_time(ASN1_TIME *ctm)
        atm.length=sizeof(buff2);
        atm.data=(unsigned char *)buff2;
 
-       X509_gmtime_adj(&atm,-offset*60);
+       X509_time_adj(&atm,-offset*60, cmp_time);
 
        if(ctm->type == V_ASN1_UTCTIME)
                {
@@ -614,10 +621,17 @@ int X509_cmp_current_time(ASN1_TIME *ctm)
        }
 
 ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
+{
+       return X509_time_adj(s, adj, NULL);
+}
+
+ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm)
        {
        time_t t;
 
-       time(&t);
+       if(in_tm) t = *in_tm;
+       else time(&t);
+
        t+=adj;
        if(!s) return ASN1_TIME_set(s, t);
        if(s->type == V_ASN1_UTCTIME) return(ASN1_UTCTIME_set(s,t));
@@ -855,6 +869,17 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
        memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
        }
 
+void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, long flags)
+       {
+               ctx->flags |= flags;
+       }
+
+void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, long flags, time_t t)
+       {
+               ctx->check_time = t;
+               ctx->flags |= X509_V_FLAG_USE_CHECK_TIME;
+       }
+
 IMPLEMENT_STACK_OF(X509)
 IMPLEMENT_ASN1_SET_OF(X509)
 
index 71d56bb..ba8cac5 100644 (file)
@@ -380,6 +380,8 @@ int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
 int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
 int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
                                int purpose, int trust);
+void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, long flags);
+void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, long flags, time_t t);
 
 #ifdef  __cplusplus
 }
diff --git a/doc/apps/rsautl.pod b/doc/apps/rsautl.pod
new file mode 100644 (file)
index 0000000..6a2466a
--- /dev/null
@@ -0,0 +1,181 @@
+=pod
+
+=head1 NAME
+
+rsautl - RSA utility
+
+=head1 SYNOPSIS
+
+B<openssl> B<rsautl>
+[B<-in file>]
+[B<-out file>]
+[B<-inkey file>]
+[B<-pubin>]
+[B<-certin>]
+[B<-sign>]
+[B<-verify>]
+[B<-encrypt>]
+[B<-decrypt>]
+[B<-pkcs>]
+[B<-ssl>]
+[B<-raw>]
+[B<-hexdump>]
+[B<-asn1parse>]
+
+=head1 DESCRIPTION
+
+The B<rsautl> command can be used to sign, verify, encrypt and decrypt
+data using the RSA algorithm.
+
+=head1 COMMAND OPTIONS
+
+=over 4
+
+=item B<-in filename>
+
+This specifies the input filename to read data from or standard input
+if this option is not specified.
+
+=item B<-out filename>
+
+specifies the output filename to write to or standard output by
+default.
+
+=item B<-inkey file>
+
+the input key file, by default it should be an RSA private key.
+
+=item B<-pubin>
+
+the input file is an RSA public key. 
+
+=item B<-certin>
+
+the input is a certificate containing an RSA public key. 
+
+=item B<-sign>
+
+sign the input data and output the signed result. This requires
+and RSA private key.
+
+=item B<-verify>
+
+verify the input data and output the recovered data.
+
+=item B<-encrypt>
+
+encrypt the input data using an RSA public key.
+
+=item B<-decrypt>
+
+decrypt the input data using an RSA private key.
+
+=item B<-pkcs, -ssl, -raw>
+
+the padding to use, PKCS#1 v1.5 (the default) SSL v2 or no padding
+respectively.
+
+=item B<-hexdump>
+
+hex dump the output data.
+
+=item B<-asn1parse>
+
+asn1parse the output data, this is useful when combined with the
+B<-verify> option.
+
+=back
+
+=head1 NOTES
+
+B<rsautl> because it uses the RSA algorithm directly can only be
+used to sign or verify small pieces of data.
+
+=head1 EXAMPLES
+
+Sign the some data using a private key:
+
+ openssl rsautl -sign -in file -inkey key.pem -out sig
+
+Recover the signed data
+
+ openssl rsautl -sign -in sig -inkey key.pem
+
+Examine the raw signed data:
+
+ openssl rsautl -sign -in file -inkey key.pem -raw -hexdump
+
+ 0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
+ 0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
+ 0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
+ 0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
+ 0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
+ 0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
+ 0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
+ 0070 - ff ff ff ff 00 68 65 6c-6c 6f 20 77 6f 72 6c 64   .....hello world
+
+The PKCS#1 block formatting is evident from this. If this was done using
+encrypt and decrypt the block would have been of type 2 (the second byte)
+and random padding data visible instead of the 0xff bytes.
+
+It is possible to analyse the signature of certificates using this
+utility in conjunction with B<asn1parse>. Consider the self signed
+example in certs/pca-cert.pem . Running B<asn1parse> as follows yields:
+
+ openssl asn1parse -in pca-cert.pem
+
+    0:d=0  hl=4 l= 742 cons: SEQUENCE          
+    4:d=1  hl=4 l= 591 cons:  SEQUENCE          
+    8:d=2  hl=2 l=   3 cons:   cont [ 0 ]        
+   10:d=3  hl=2 l=   1 prim:    INTEGER           :02
+   13:d=2  hl=2 l=   1 prim:   INTEGER           :00
+   16:d=2  hl=2 l=  13 cons:   SEQUENCE          
+   18:d=3  hl=2 l=   9 prim:    OBJECT            :md5WithRSAEncryption
+   29:d=3  hl=2 l=   0 prim:    NULL              
+   31:d=2  hl=2 l=  92 cons:   SEQUENCE          
+   33:d=3  hl=2 l=  11 cons:    SET               
+   35:d=4  hl=2 l=   9 cons:     SEQUENCE          
+   37:d=5  hl=2 l=   3 prim:      OBJECT            :countryName
+   42:d=5  hl=2 l=   2 prim:      PRINTABLESTRING   :AU
+  ....
+  599:d=1  hl=2 l=  13 cons:  SEQUENCE          
+  601:d=2  hl=2 l=   9 prim:   OBJECT            :md5WithRSAEncryption
+  612:d=2  hl=2 l=   0 prim:   NULL              
+  614:d=1  hl=3 l= 129 prim:  BIT STRING        
+
+
+The final BIT STRING contains the actual signature. It can be extracted with:
+
+ openssl asn1parse -in pca-cert.pem -out sig -noout -strparse 614
+
+The certificate public key can be extracted with:
+ openssl x509 -in test/testx509.pem -pubout -noout >pubkey.pem
+
+The signature can be analysed with:
+
+ openssl rsautl -in sig -verify -asn1parse -inkey pubkey.pem -pubin
+
+    0:d=0  hl=2 l=  32 cons: SEQUENCE          
+    2:d=1  hl=2 l=  12 cons:  SEQUENCE          
+    4:d=2  hl=2 l=   8 prim:   OBJECT            :md5
+   14:d=2  hl=2 l=   0 prim:   NULL              
+   16:d=1  hl=2 l=  16 prim:  OCTET STRING      
+      0000 - f3 46 9e aa 1a 4a 73 c9-37 ea 93 00 48 25 08 b5   .F...Js.7...H%..
+
+This is the parsed version of an ASN1 DigestInfo structure. It can be seen that
+the digest used was md5. The actual part of the certificate that was signed can
+be extracted with:
+
+ openssl asn1parse -in pca-cert.pem -out tbs -noout -strparse 4
+
+and its digest computed with:
+
+ openssl md5 -c tbs
+ MD5(tbs)= f3:46:9e:aa:1a:4a:73:c9:37:ea:93:00:48:25:08:b5
+
+which it can be seen agrees with the recovered value above.
+
+=head1 SEE ALSO
+
+L<dgst(1)|dgst(1)>, L<rsa(1)|rsa(1)>, L<genrsa(1)|genrsa(1)>