Index: creddy/creddy.c
===================================================================
--- creddy/creddy.c	(revision 9410b51d74724a747c1abec44349565d48d79c0d)
+++ creddy/creddy.c	(revision 784a398306980ced8f2abd5cb683a88ab5091719)
@@ -16,4 +16,5 @@
 #define OPT_SUBJECT_ROLE    8
 #define OPT_OUT             9 // the world oughta be opt-in only :(
+#define OPT_ATTRCERT        10
 
 int main(int argc, char **argv) {
@@ -43,4 +44,7 @@
         { "out",          1, 0, OPT_OUT },
 
+        // verify option
+        { "attrcert",   1, 0, OPT_ATTRCERT },
+
         { NULL },
     };
@@ -86,4 +90,9 @@
             case OPT_OUT:
                 options.out = xstrdup(optarg);
+                break;
+
+            // verify options
+            case OPT_ATTRCERT:
+                options.attrcert = xstrdup(optarg);
                 break;
 
@@ -137,4 +146,8 @@
             break;
 
+        case MODE_VERIFY:
+            verify_main(&options);
+            break;
+
         default:
             usage(&options);
@@ -236,2 +249,14 @@
     return cert;
 }
+
+certificate_t *attr_cert_from_file(char *filename) {
+    certificate_t *cert = lib->creds->create(lib->creds,
+        CRED_CERTIFICATE, CERT_X509_AC,
+        BUILD_FROM_FILE, filename,
+        BUILD_END
+    );
+    if (cert == NULL)
+        errx(1, "Couldn't load attribute cert %s", filename);
+
+    return cert;
+}
Index: creddy/creddy.h
===================================================================
--- creddy/creddy.h	(revision 9410b51d74724a747c1abec44349565d48d79c0d)
+++ creddy/creddy.h	(revision 784a398306980ced8f2abd5cb683a88ab5091719)
@@ -23,4 +23,7 @@
     char *subject_role;
     char *out;
+
+    // verify options
+    char *attrcert;
 } options_t;
 
@@ -34,6 +37,7 @@
 int clean_name(char *string);
 
-// load an ID cert from file (aborts on fail)
+// load an ID/attr cert from file (aborts on fail)
 certificate_t *cert_from_file(char *filename);
+certificate_t *attr_cert_from_file(char *filename);
 
 // get the keyid from a cert (free result when done)
@@ -52,4 +56,5 @@
 void attribute_main(options_t *opts);
 void roles_main(options_t *opts);
+void verify_main(options_t *opts);
 
 #endif /* __CREDDY_H__ */
Index: creddy/roles.c
===================================================================
--- creddy/roles.c	(revision 9410b51d74724a747c1abec44349565d48d79c0d)
+++ creddy/roles.c	(revision 784a398306980ced8f2abd5cb683a88ab5091719)
@@ -7,11 +7,5 @@
         usage(opts);
 
-    certificate_t *cert = lib->creds->create(lib->creds,
-        CRED_CERTIFICATE, CERT_X509_AC,
-        BUILD_FROM_FILE, opts->cert,
-        BUILD_END
-    );
-    if (cert == NULL)
-        errx(1, "Couldn't load attribute cert %s", opts->cert);
+    certificate_t *cert = attr_cert_from_file(opts->cert);
 
     ac_t *ac = (ac_t *)cert;
Index: creddy/verify.c
===================================================================
--- creddy/verify.c	(revision 784a398306980ced8f2abd5cb683a88ab5091719)
+++ creddy/verify.c	(revision 784a398306980ced8f2abd5cb683a88ab5091719)
@@ -0,0 +1,35 @@
+#include "creddy.h"
+
+void verify_main(options_t *opts) {
+    certificate_t *subject_cert = NULL;
+
+    if (opts->cert == NULL)
+        usage(opts);
+
+    certificate_t *cert = cert_from_file(opts->cert);
+
+    if (opts->attrcert != NULL)
+        subject_cert = attr_cert_from_file(opts->attrcert);
+    else
+        subject_cert = cert;
+
+    int good = 0;
+    if (subject_cert->issued_by(subject_cert, cert))
+        if (subject_cert->get_validity(subject_cert, NULL, NULL, NULL))
+            if (cert->get_validity(cert, NULL, NULL, NULL)) {
+                puts("signature good, certificates valid");
+                good = 1;
+            }
+            else
+                puts("signature good, issuer cert not valid now");
+        else
+            puts("certificate not valid now");
+    else
+        puts("signature invalid");
+
+    if (subject_cert != cert)
+        DESTROY_IF(subject_cert);
+    DESTROY_IF(cert);
+
+    exit(good);
+}
