diff -ur pluto-orig/connections.c ./connections.c
--- pluto-orig/connections.c	Mon Sep  4 19:57:16 2000
+++ ./connections.c	Mon Sep  4 18:05:49 2000
@@ -484,6 +484,9 @@
 	c->sa_rekey_fuzz = wm->sa_rekey_fuzz;
 	c->sa_keying_tries = wm->sa_keying_tries;
 
+	c->this.id.key_id.len = 0;
+        c->that.id.key_id.len = 0;
+
 	extract_end(&c->this, &wm->left, "left");
 	extract_end(&c->that, &wm->right, "right");
 
diff -ur pluto-orig/defs.h ./defs.h
--- pluto-orig/defs.h	Mon Sep  4 19:57:16 2000
+++ ./defs.h	Mon Sep  4 18:07:03 2000
@@ -121,3 +121,10 @@
 
 /* pad_up(n, m) is the amount to add to n to make it a multiple of m */
 #define pad_up(n, m) (((m) - 1) - (((n) + (m) - 1) % (m)))
+
+typedef struct pc{
+       char *cert;
+       int cert_len;
+       } pc;
+
+struct pc pgpcert;
diff -ur pluto-orig/demux.c ./demux.c
--- pluto-orig/demux.c	Mon Sep  4 19:57:16 2000
+++ ./demux.c	Mon Sep  4 18:15:03 2000
@@ -229,7 +229,7 @@
      *	    --> HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
      */
     { STATE_MAIN_R1, SMF_PSK_AUTH | SMF_DS_AUTH
-    , P(KE) | P(NONCE), P(VID), PT(KE)
+    , P(KE) | P(NONCE), P(VID) | P(CR), PT(KE)
     , EVENT_RETRANSMIT, main_inI2_outR2 },
 
     { STATE_MAIN_R1, SMF_PKE_AUTH
@@ -251,11 +251,11 @@
      *	    --> HDR*, HASH_I
      */
     { STATE_MAIN_I2, SMF_PSK_AUTH | SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
-    , P(KE) | P(NONCE), P(VID), PT(ID)
+    , P(KE) | P(NONCE), P(VID) | P(CR), PT(ID)
     , EVENT_RETRANSMIT, main_inR2_outI3 },
 
     { STATE_MAIN_I2, SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
-    , P(KE) | P(ID) | P(NONCE), P(VID), PT(HASH)
+    , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR), PT(HASH)
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
 
     { STATE_MAIN_I2, SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
@@ -274,7 +274,7 @@
     , EVENT_SA_REPLACE, main_inI3_outR3 },
 
     { STATE_MAIN_R2, SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
-    , P(ID) | P(SIG), P(VID) | P(CERT), PT(ID)
+    , P(ID) | P(SIG), P(VID) | P(CERT) | P(CR), PT(ID)
     , EVENT_SA_REPLACE, main_inI3_outR3 },
 
     { STATE_MAIN_R2, SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
@@ -292,7 +292,7 @@
     , EVENT_SA_REPLACE, main_inR3 },
 
     { STATE_MAIN_I3, SMF_DS_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
-    , P(ID) | P(SIG), P(VID) | P(CERT), PT(NONE)
+    , P(ID) | P(SIG), P(VID) | P(CERT) | P(CR), PT(NONE)
     , EVENT_SA_REPLACE, main_inR3 },
 
     { STATE_MAIN_I3, SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
diff -ur pluto-orig/id.c ./id.c
--- pluto-orig/id.c	Mon Sep  4 19:57:16 2000
+++ ./id.c	Mon Sep  4 18:25:29 2000
@@ -37,6 +37,10 @@
 {
     complaint_t ugh = NULL;
 
+    char *nptr, *kptr;
+    char s[4];
+    u_int i;
+    
     memset(id, 0, sizeof(*id));
     id->name.ptr = NULL;
     id->next = NULL;
@@ -50,18 +54,35 @@
     {
 	if (*src == '@')
 	{
-	    id->kind = ID_FQDN;
-	    id->name.ptr = src+1;	/* discard @ */
-	}
-	else
-	{
-	    /* We leave in @, as per DOI 4.6.2.4
-	     * (but DNS wants . instead).
-	     */
-	    id->kind = ID_USER_FQDN;
-	    id->name.ptr = src;
-	}
-	id->name.len = strlen(id->name.ptr);
+               if (*(src+1) == '#')
+               {
+                       id->kind = ID_KEY_ID;
+                       id->name.ptr = src+2;
+                       id->key_id.ptr = alloc_bytes(strlen(id->name.ptr)/2, "keyid-ptr");
+                       id->key_id.len = strlen(id->name.ptr)/2;
+                       nptr = id->name.ptr;
+                       kptr = id->key_id.ptr;
+
+                       for (i=0; i< strlen(id->name.ptr)/2; i++, kptr++)
+                       {
+                               snprintf(s, 3, "%s", nptr);
+                               *kptr = strtol(s, NULL, 16);
+                               nptr+=2;
+                       }
+                       DBG_dump("Key-ID: ", id->key_id.ptr, id->key_id.len);
+               }
+               else
+               {
+                       id->kind = ID_FQDN;
+                       id->name.ptr = src+1;   /* discard @ */
+               }
+       }
+       else
+       {
+               id->kind = ID_USER_FQDN;
+               id->name.ptr = src;
+       }
+       id->name.len = strlen(id->name.ptr);
     }
     return ugh;
 }
@@ -79,6 +100,8 @@
 	return snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
     case ID_USER_FQDN:
 	return snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr);
+    case ID_KEY_ID:
+        return snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr);
     default:
 	return snprintf(dst, dstlen, "unknown id kind %d", id->kind);
     }
@@ -101,18 +124,20 @@
 void
 clone_id_content(struct id *id)
 {
-    switch (id->kind)
-    {
-    case ID_FQDN:
-    case ID_USER_FQDN:
-	id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name");
-	break;
-    case ID_NONE:
-    case ID_IPV4_ADDR:
-	break;
-    default:
-	passert(FALSE);
-    }
+switch (id->kind)
+     {
+     case ID_KEY_ID:
+        id->key_id.ptr = clone_bytes(id->key_id.ptr, id->key_id.len,"keep keyid");
+     case ID_FQDN:
+     case ID_USER_FQDN:
+        id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name");
+        break;
+     case ID_NONE:
+     case ID_IPV4_ADDR:
+        break;
+     default:
+        passert(FALSE);
+     }
 }
 
 /* free a heap struct id */
@@ -132,6 +157,10 @@
     case ID_USER_FQDN:
 	pfree(id->name.ptr);
 	break;
+    case ID_KEY_ID:
+       pfree(id->name.ptr);
+       pfree(id->key_id.ptr);
+       break;
     case ID_NONE:
     case ID_IPV4_ADDR:
 	break;
@@ -156,6 +185,7 @@
 
     case ID_FQDN:
     case ID_USER_FQDN:
+    case ID_KEY_ID:
 	/* assumption: case should be ignored */
 	return a->name.len == b->name.len
 	    && strncasecmp(a->name.ptr, b->name.ptr, a->name.len) == 0;
@@ -185,6 +215,9 @@
 	tl->ptr = (void *)&end->id.ip_addr;
 	tl->len = sizeof(end->id.ip_addr);
 	break;
+    case ID_KEY_ID:
+        *tl = end->id.key_id;
+        break;
     default:
 	passert(FALSE);
     }
diff -ur pluto-orig/id.h ./id.h
--- pluto-orig/id.h	Mon Sep  4 19:57:16 2000
+++ ./id.h	Mon Sep  4 18:26:43 2000
@@ -18,6 +18,7 @@
     int kind;	/* ID_* value */
     struct in_addr ip_addr;	/* (network order) ID_IPV4_ADDR */
     chunk_t name;	/* ID_FQDN, ID_USER_FQDN (with @) */
+    chunk_t key_id;
     struct id *next;
 };
 
diff -ur pluto-orig/ipsec_doi.c ./ipsec_doi.c
--- pluto-orig/ipsec_doi.c	Mon Sep  4 19:57:16 2000
+++ ./ipsec_doi.c	Mon Sep  4 19:54:41 2000
@@ -53,6 +53,14 @@
 #define RETURN_STF_FAILURE(f) \
     { int r = (f); if (r != NOTHING_WRONG) return STF_FAIL + r; }
 
+stf_status send_delete(struct state *p2st, ipsec_spi_t *spi, bool ESP);
+static bool encrypt_message(pb_stream *pbs, struct state *st);
+
+/* needed for PGPnet Vendor ID */
+char pgp_vid[] = { 0x4f, 0x70, 0x65, 0x6e,
+                0x50, 0x47, 0x50, 0x31,
+                0x30, 0x31, 0x37, 0x31};
+
 /* if we haven't already done so, compute a local DH secret (st->st_sec) and
  * the corresponding public value (g).  This is emitted as a KE payload.
  */
@@ -258,6 +266,120 @@
 //}
 #endif /* not currently used */
 
+stf_status
+send_delete(struct state *p2st, ipsec_spi_t *spi, bool ESP)
+{
+     pb_stream reply_pbs;
+     pb_stream r_hdr_pbs;
+     msgid_t   msgid;
+     u_char    old_new_iv[MAX_DIGEST_LEN];
+     u_char    old_iv[MAX_DIGEST_LEN];
+     u_char buffer[8192];
+     struct state *p1st;
+
+     u_char spilen = sizeof(ipsec_spi_t);
+     u_char
+       *r_hashval,     /* where in reply to jam hash value */
+       *r_hash_start;  /* start of what is to be hashed */
+
+     memset(buffer, '\0', sizeof(buffer));
+     init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg");
+
+     /* find the related P1-State to the calling P2-state */
+     p1st = find_state(p2st->st_icookie, p2st->st_rcookie,
+                       p2st->st_connection->that.host_addr, 0);
+     if (p1st == NULL)
+     {
+       DBG_log("no phase 1 state where one should be");
+       return STF_INTERNAL_ERROR;
+     }
+
+/*     msgid = generate_msgid(p1st->st_connection->that.host_addr); */
+
+/* WORKAROUND: the above struct doesn't work now; I had to replace it with this new one */        
+       msgid = generate_msgid(p1st);
+	     
+     /* HDR* */
+     {
+       struct isakmp_hdr hdr;
+
+       hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
+       hdr.isa_np = ISAKMP_NEXT_HASH;
+       hdr.isa_xchg = ISAKMP_XCHG_INFO;
+       hdr.isa_msgid = msgid;
+       hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
+       memcpy(hdr.isa_icookie, p1st->st_icookie, COOKIE_SIZE);
+       memcpy(hdr.isa_rcookie, p1st->st_rcookie, COOKIE_SIZE);
+       if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_pbs, &r_hdr_pbs))
+           return STF_INTERNAL_ERROR;
+     }
+
+     /* HASH -- space to be filled later */
+     {
+       pb_stream hash_pbs;
+
+       if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs))
+           return STF_INTERNAL_ERROR;
+       r_hashval = hash_pbs.cur;       /* remember where to plant value */
+       if (!out_zero(p1st->st_oakley.hasher->hash_digest_len, &hash_pbs, "HASH(1)"))
+           return STF_INTERNAL_ERROR;
+       close_output_pbs(&hash_pbs);
+       r_hash_start = r_hdr_pbs.cur;   /* hash from after HASH(1) */
+     }
+
+     /* DELETE PAYLOAD */
+     {
+       pb_stream del_pbs;
+       struct isakmp_delete isad;
+
+        isad.isad_doi = ISAKMP_DOI_IPSEC;
+       isad.isad_np = ISAKMP_NEXT_NONE;
+       isad.isad_spisize = spilen;
+        if (ESP) isad.isad_protoid = PROTO_IPSEC_ESP;
+        else isad.isad_protoid = PROTO_IPSEC_AH;
+       isad.isad_nospi = 0x0001;
+         if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs))
+           return STF_INTERNAL_ERROR;
+       if (!out_raw(spi, spilen, &del_pbs, "delete payload"))
+           return STF_INTERNAL_ERROR;;
+         close_output_pbs(&del_pbs);
+     }
+
+     {
+         struct hmac_ctx ctx;
+       hmac_init_chunk(&ctx, p1st->st_oakley.hasher, p1st->st_skeyid_a);
+         hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t));
+         hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start);
+       hmac_final(r_hashval, &ctx);
+
+         DBG(DBG_CRYPT,
+           DBG_log("HASH(1) computed:");
+           DBG_dump("", r_hashval, ctx.hmac_digest_len));
+     }
+
+     /* save old IV (this prevents from copying a whole new state object
+      * for NOTIFICATION / DELETE messages we don't need to maintain a state
+      * because there are no retransmissions...
+      */
+
+     memcpy(old_new_iv, p1st->st_new_iv, p1st->st_new_iv_len);
+     memcpy(old_iv, p1st->st_iv, p1st->st_iv_len);
+     init_phase2_iv(p1st, &msgid);
+
+     if(!encrypt_message(&r_hdr_pbs, p1st)) passert(FALSE);
+
+     clonetochunk(p1st->st_tpacket, reply_pbs.start, pbs_offset(&reply_pbs)
+       , "reply packet for main_outI1");
+
+     send_packet(p1st, "delete notify");
+
+     /* get back old IV for this state */
+     memcpy(p1st->st_new_iv, old_new_iv, p1st->st_new_iv_len);
+     memcpy(p1st->st_iv, old_iv, p1st->st_iv_len);
+
+     return STF_IGNORE;
+}
+
 /* The whole message must be a multiple of 4 octets.
  * I'm not sure where this is spelled out, but look at
  * rfc2408 3.6 Transform Payload.
@@ -290,6 +412,7 @@
 
     struct state *st;
 
+    int np;
     /* set up new state */
     cur_state = st = new_state();
     st->st_connection = c;
@@ -358,9 +481,15 @@
 		return STF_INTERNAL_ERROR;
 	    }
 	}
+
+        if (c->this.id.kind == ID_KEY_ID)
+                np = ISAKMP_NEXT_VID;
+        else
+                np = ISAKMP_NEXT_NONE;
+	
 	if (!out_sa(&rbody
 	, &oakley_sadb[auth_policy >> POLICY_ISAKMP_SHIFT]
-	, st, TRUE, ISAKMP_NEXT_NONE))
+	, st, TRUE, np))
 	{
 	    cur_state = NULL;
 	    return STF_INTERNAL_ERROR;
@@ -372,6 +501,12 @@
 	    , "sa in main_outI1");
     }
 
+    if (c->this.id.kind == ID_KEY_ID)
+    {
+       if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_vendor_id_desc, &rbody, pgp_vid, sizeof(pgp_vid), "V_ID"))
+               return STF_INTERNAL_ERROR;
+    }
+
     close_message(&rbody);
     close_output_pbs(&reply);
 
@@ -708,6 +843,10 @@
 		, enum_show(&ident_names, id_hd.isaiid_idtype)
 		, id_hd.isaiid_protoid, htons(id_hd.isaiid_port)));
 
+       DBG_dump("ID to be hashed:"
+               , (u_char *)&id_hd + sizeof(struct isakmp_generic)
+               , sizeof(id_hd) - sizeof(struct isakmp_generic));
+
 	/* NOTE: hash does NOT include the generic payload part of
 	 * Identity Payload
 	 */
@@ -715,6 +854,8 @@
 	    , (u_char *)&id_hd + sizeof(struct isakmp_generic)
 	    , sizeof(id_hd) - sizeof(struct isakmp_generic));
 
+       DBG_dump("ID to be hashed:", id_b.ptr, id_b.len);
+
 	hash_update_chunk(ctx, id_b);
     }
 #   undef hash_update_chunk
@@ -1296,6 +1437,10 @@
     pb_stream *const id_pbs = &id_pld->pbs;
     struct isakmp_id *const id = &id_pld->payload.id;
     struct id peer;
+    u_char key_id[256];
+    u_int i, len;
+
+    peer.key_id.len = 0;
 
     /* XXX Check for valid ID types? */
     peer.kind = id->isaid_idtype;
@@ -1361,6 +1506,43 @@
 	setchunk(peer.name, id_pbs->cur, pbs_left(id_pbs));
 	break;
 
+    case ID_KEY_ID:
+       if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0))
+       {
+           log("protocol/port in Phase 1 ID Payload must be 0/0"
+               " but are %d/%d"
+               , id->isaid_doi_specific_a, id->isaid_doi_specific_b);
+           return FALSE;
+       }
+
+       len = pbs_left(id_pbs);
+
+       /* we need double size for ASCII representation of key id */
+       if (2*len > 256)
+       {
+               log("too large key id");
+               return FALSE;
+       }
+
+       DBG_dump("Key ID:", id_pbs->cur, pbs_left(id_pbs));
+
+       /* hold the binary representation of KEY_ID */
+       /* possible memory hole? */
+
+       peer.key_id.ptr = alloc_bytes(len, "key_id");
+       peer.key_id.len = len;
+       memcpy(peer.key_id.ptr, id_pbs->cur, len);
+
+       for (i=0; i<len; i++, id_pbs->cur++)
+               sprintf(&key_id[i*2], "%02x", *(id_pbs->cur));
+
+       /* possible memory hole? */
+       peer.name.ptr = alloc_bytes(2*len, "name");
+       peer.name.len = 2*len;
+       memcpy(peer.name.ptr, key_id, peer.name.len);
+
+       break;
+
     default:
 	/* XXX Could send notification back */
 	loglog(RC_LOG_SERIOUS, "Unacceptable identity type (%s) in Phase 1 ID Payload"
@@ -1413,6 +1595,11 @@
 	    SET_CUR_CONNECTION(r);
 	    rw_connection_discard(c);
 	}
+        if (peer.key_id.len)
+        {
+                r->that.id.key_id.ptr = clone_bytes( peer.key_id.ptr, peer.key_id.len, "KEY_ID");
+                r->that.id.key_id.len = peer.key_id.len;
+        }
     }
 
     return TRUE;
@@ -1795,7 +1982,11 @@
     {
 	struct isakmp_sa r_sa = sa_pd->payload.sa;
 
-	r_sa.isasa_np = ISAKMP_NEXT_NONE;
+        if (c->this.id.kind == ID_KEY_ID)
+                r_sa.isasa_np = ISAKMP_NEXT_VID;
+        else
+                r_sa.isasa_np = ISAKMP_NEXT_NONE;
+
 	if (!out_struct(&r_sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs))
 	    return STF_INTERNAL_ERROR;
     }
@@ -1803,6 +1994,11 @@
     /* SA body in and out */
     RETURN_STF_FAILURE(parse_isakmp_sa_body(&sa_pd->pbs, &sa_pd->payload.sa, &r_sa_pbs
 	    , FALSE, st));
+     if (c->this.id.kind == ID_KEY_ID)
+     {
+        if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_vendor_id_desc, &md->rbody, pgp_vid, sizeof(pgp_vid), "V_ID"))
+                return STF_INTERNAL_ERROR;
+     }
     close_message(&md->rbody);
 
     /* save initiator SA for HASH */
@@ -1941,6 +2137,8 @@
 main_inR2_outI3(struct msg_digest *md)
 {
     struct state *const st = md->st;
+    pb_stream cert_pbs;
+    u_char cert_type = 2;
     pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
     int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
 	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
@@ -1973,12 +2171,25 @@
 	pb_stream id_pbs;
 
 	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
-	id_hd.isaiid_np = auth_payload;
+        if ( (pgpcert.cert_len) && (st->st_oakley.auth == OAKLEY_RSA_SIG) )
+                        id_hd.isaiid_np = ISAKMP_NEXT_CERT;
+        else id_hd.isaiid_np = auth_payload;
+
 	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &id_pbs)
 	|| !out_chunk(id_b, &id_pbs, "my identity"))
 	    return STF_INTERNAL_ERROR;
 	close_output_pbs(&id_pbs);
     }
+    if (pgpcert.cert_len && st->st_oakley.auth == OAKLEY_RSA_SIG)
+    {
+       if (!out_generic(ISAKMP_NEXT_SIG, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
+               return STF_INTERNAL_ERROR;
+       if (!out_raw(&cert_type, sizeof(cert_type), &cert_pbs, "cert type"))
+               return STF_INTERNAL_ERROR;
+       if (!out_raw(pgpcert.cert, pgpcert.cert_len, &cert_pbs, "pgp cert"))
+               return STF_INTERNAL_ERROR;
+       close_output_pbs(&cert_pbs);
+    }
 
     /* HASH_I or SIG_I out */
     {
@@ -2032,6 +2243,8 @@
 main_inI3_outR3(struct msg_digest *md)
 {
     struct state *const st = md->st;
+    pb_stream cert_pbs;
+    u_char cert_type = 2;
     int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
 	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
 
@@ -2054,11 +2267,24 @@
 	pb_stream r_id_pbs;
 
 	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
-	id_hd.isaiid_np = auth_payload;
+        if ( (pgpcert.cert_len) && (st->st_oakley.auth == OAKLEY_RSA_SIG) )
+                        id_hd.isaiid_np = ISAKMP_NEXT_CERT;
+        else
+                        id_hd.isaiid_np = auth_payload;
 	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &r_id_pbs)
 	|| !out_chunk(id_b, &r_id_pbs, "my identity"))
 	    return STF_INTERNAL_ERROR;
 	close_output_pbs(&r_id_pbs);
+       }
+       if (pgpcert.cert_len && st->st_oakley.auth == OAKLEY_RSA_SIG)
+       {
+               if (!out_generic(ISAKMP_NEXT_SIG, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
+                       return STF_INTERNAL_ERROR;
+               if (!out_raw(&cert_type, sizeof(cert_type), &cert_pbs, "cert type"))
+                       return STF_INTERNAL_ERROR;
+               if (!out_raw(pgpcert.cert, pgpcert.cert_len, &cert_pbs, "pgp cert"))
+                       return STF_INTERNAL_ERROR;
+       close_output_pbs(&cert_pbs);
     }
 
     /* HASH_R or SIG_R out */
diff -ur pluto-orig/kernel.c ./kernel.c
--- pluto-orig/kernel.c	Mon Sep  4 19:57:17 2000
+++ ./kernel.c	Mon Sep  4 18:58:40 2000
@@ -48,6 +48,7 @@
 #include "server.h"
 #include "whack.h"	/* for RC_LOG_SERIOUS */
 
+extern int send_delete(struct state *st, ipsec_spi_t *spi, bool ESP);
 
 bool no_klips = FALSE;	/* don't actually use KLIPS */
 
@@ -1003,6 +1004,8 @@
     {
 	passert(FALSE);	/* neither AH nor ESP in outbound SA bundle! */
     }
+
+    send_delete(st, &f->our_spi, proto==SA_ESP?TRUE:FALSE);
 
     return inbound
 	? del_spi(f->our_spi, proto, c->that.host_addr, c->this.host_addr)
diff -ur pluto-orig/main.c ./main.c
--- pluto-orig/main.c	Mon Sep  4 19:57:17 2000
+++ ./main.c	Mon Sep  4 19:00:24 2000
@@ -156,6 +156,9 @@
     bool log_to_stderr_desired = FALSE;
     int lockfd;
 
+    FILE *fd = NULL;
+    int i;
+
     /* handle arguments */
     for (;;)
     {
@@ -376,6 +379,19 @@
     }
 
     close(lockfd);
+
+    fd = fopen("/etc/pgpcert.pgp", "r");
+    if (fd)
+    {
+       log("Loading my PGP certificate...");
+       fseek(fd, 0, SEEK_END );
+       pgpcert.cert_len = ftell(fd);
+       rewind(fd);
+       pgpcert.cert = alloc_bytes(pgpcert.cert_len, "pgp cert");
+       i = fread(pgpcert.cert, 1, pgpcert.cert_len, fd);
+       fclose(fd);
+       log("%d bytes loaded", i);
+    }
 
     init_log();
     /* Note: some scripts may look for this exact message -- don't change */
diff -ur pluto-orig/preshared.c ./preshared.c
--- pluto-orig/preshared.c	Mon Sep  4 19:57:17 2000
+++ ./preshared.c	Mon Sep  4 19:02:37 2000
@@ -140,10 +140,11 @@
     mpz_sub(u, u, &k->q);
     mpz_add_ui(u, u, 1);
 
-    mpz_mul(t, &k->d, &k->pub.e);
+/*    mpz_mul(t, &k->d, &k->pub.e);
     mpz_mod(t, t, u);
     if (mpz_cmp_ui(t, 1) != 0)
 	ugh = "(d * e) mod ((p-1) * (q-1)) != 1";
+*/
 
     /* check that dP is d mod (p-1) */
     mpz_sub_ui(u, &k->p, 1);
