Index: libabac/abac_xml.c
===================================================================
--- libabac/abac_xml.c	(revision d2b198c77ec345f4a2f4f7c24f7d28230cb6faad)
+++ libabac/abac_xml.c	(revision f520b1ed74a0c375b8bf912e662b7be6bed67640)
@@ -1139,5 +1139,6 @@
 
 /* Template to create a head element in structured XML for RT0 (v1.1).  All
- * heads are a single role element */
+ * heads are a single role element. There aer versions with and without
+ * mnemonics. */
 static char *head_template = 
 "<head>\n"
@@ -1146,6 +1147,13 @@
 "</head>\n";
 
+static char *head_template_w_mnemonic = 
+"<head>\n"
+"   <ABACprincipal><keyid>%s</keyid><mnemonic>%s</mnemonic></ABACprincipal>\n"
+"   <role>%s</role>\n"
+"</head>\n";
+
 /* Templates to create a tail in structured XML  based on how many of
- * principal, role, and linking role are present. */
+ * principal, role, and linking role are present. There are variants with
+ * and without mnomonics. */
 static char *tail_template[] = {
 "<tail>\n"
@@ -1162,4 +1170,98 @@
 "</tail>\n",
 };
+static char *tail_template_w_mnemonic[] = {
+"<tail>\n"
+"   <ABACprincipal><keyid>%s</keyid><mnemonic>%s</mnemonic></ABACprincipal>\n"
+"</tail>\n",
+"<tail>\n"
+"   <ABACprincipal><keyid>%s</keyid><mnemonic>%s</mnemonic></ABACprincipal>\n"
+"   <role>%s</role>\n"
+"</tail>\n",
+"<tail>\n"
+"   <ABACprincipal><keyid>%s</keyid><mnemonic>%s</mnemonic></ABACprincipal>\n"
+"   <role>%s</role>\n"
+"   <linking_role>%s</linking_role>\n"
+"</tail>\n",
+};
+
+/* These three functions are variations on the theme of printing out the XML
+ * representation of tail roles in the XML credential.  They're separated out
+ * to make reading encode_rt0_xml_v11 a little easier.  Each prints the role
+ * (r) into the string tmp, adding mnemonic annotations from km if present.  Sz
+ * is the number of bytes remaining in the overall string, and is always
+ * smaller than the size of tmp.  The only differences are which templates are
+ * used and how many strings are inserted.  The length of the generated string
+ * is returned.
+ */
+static int encode_principal_role(abac_role_t *r, char *tmp,  int sz,
+	abac_keyid_map_t *km) {
+    char *p = minimal_xml_escaping(abac_role_principal(r));
+    char *nick = NULL;
+    int ts = 0;
+
+    if ( km ) 
+	nick = abac_keyid_map_key_to_nickname(km, p);
+
+    if (nick) {
+	ts = snprintf(tmp, sz, tail_template_w_mnemonic[0], p, nick);
+	free(nick);
+	nick = NULL;
+    }
+    else {
+	ts = snprintf(tmp, sz, tail_template[0], p);
+    }
+    free(p);
+    return ts;
+}
+
+static int encode_single_role(abac_role_t *r, char *tmp,  int sz,
+	abac_keyid_map_t *km) {
+    char *p = minimal_xml_escaping(abac_role_principal(r));
+    char *ro = minimal_xml_escaping(abac_role_role_name(r));
+    char *nick = NULL;
+    int ts = 0;
+
+    if ( km ) 
+	nick = abac_keyid_map_key_to_nickname(km, p);
+
+    if (nick) {
+	ts = snprintf(tmp, sz, tail_template_w_mnemonic[0], 
+		p, nick, ro);
+	free(nick);
+	nick = NULL;
+    }
+    else {
+	ts = snprintf(tmp, sz, tail_template[1], p, ro);
+    }
+    free(p);
+    free(ro);
+    return ts;
+}
+
+static int encode_linking_role(abac_role_t *r, char *tmp,  int sz,
+	abac_keyid_map_t *km) {
+    char *p = minimal_xml_escaping(abac_role_principal(r));
+    char *ro = minimal_xml_escaping(abac_role_role_name(r));
+    char *li = minimal_xml_escaping(abac_role_linking_role(r));
+    char *nick = NULL;	    
+    int ts = 0;
+
+    if ( km ) 
+	nick = abac_keyid_map_key_to_nickname(km, p);
+
+    if (nick) {
+	ts = snprintf(tmp, sz, tail_template_w_mnemonic[2], 
+		p, nick, ro, li);
+	free(nick);
+	nick = NULL;
+    }
+    else {
+	ts = snprintf(tmp, sz, tail_template[2], p, ro, li);
+    }
+    free(p);
+    free(ro);
+    free(li);
+    return ts;
+}
 
 /* Convert the given attribute to the RT0 structured XML representation used by
@@ -1167,7 +1269,7 @@
  */
 xmlChar *encode_rt0_xml_v11(abac_attribute_t *a) {
-    int htlen = strlen(head_template);	    /* head template length */
-    int ttlen = strlen(tail_template[2]);   /* length of the longest tail
-					       template */
+    int htlen = strlen(head_template_w_mnemonic);    /* head template length */
+    int ttlen = strlen(tail_template_w_mnemonic[2]); /* length of the longest
+							tail template */
     /* Size of the string we'll need - start with a head template and string */
     int sz = strlen(abac_attribute_get_head(a)) + htlen;
@@ -1177,4 +1279,6 @@
     char *copy = abac_xstrdup(abac_attribute_get_head(a)); /* splitting */
     int npr = 2;	    /* Number of parts in the head role */
+    abac_keyid_map_t *km = (a) ? abac_attribute_get_keyid_map(a) : NULL;
+    char *nick = NULL;	    /* Mnemonic name */
     char *tmp = NULL;	    /* A temporary to build each tail element */
     char *rv = NULL;	    /* The return value */
@@ -1195,6 +1299,15 @@
 	goto fail;
 
+    if ( km ) 
+	nick = abac_keyid_map_key_to_nickname(km, princ_role[0]);
     /* Put the head in */
-    sz -= snprintf(rv, sz, head_template, princ_role[0], princ_role[1]);
+    if ( nick ) {
+	sz -= snprintf(rv, sz, head_template_w_mnemonic, princ_role[0], 
+		nick, princ_role[1]);
+	free(nick);
+	nick = NULL;
+    } else {
+	sz -= snprintf(rv, sz, head_template, princ_role[0], princ_role[1]);
+    }
 
     for ( i = 0 ; i < ntails; i++) {
@@ -1207,29 +1320,12 @@
 	    goto fail;
 
-	if ( abac_role_is_principal(r)) {
-	    char *p = minimal_xml_escaping(abac_role_principal(r));
-
-	    ts = snprintf(tmp, sz, tail_template[0], p);
-	    free(p);
-	} else if (abac_role_is_role(r)) {
-	    char *p = minimal_xml_escaping(abac_role_principal(r));
-	    char *ro = minimal_xml_escaping(abac_role_role_name(r));
-
-	    ts = snprintf(tmp, sz, tail_template[1], p, ro);
-	    free(p);
-	    free(ro);
-	} else if (abac_role_is_linking(r)) {
-	    char *p = minimal_xml_escaping(abac_role_principal(r));
-	    char *ro = minimal_xml_escaping(abac_role_role_name(r));
-	    char *li = minimal_xml_escaping(abac_role_linking_role(r));
-
-	    ts = snprintf(tmp, sz, tail_template[2], p, ro, li);
-	    free(p);
-	    free(ro);
-	    free(li);
-	}
+	if ( abac_role_is_principal(r))
+	    ts = encode_principal_role(r, tmp, sz, km);
+	else if (abac_role_is_role(r))
+	    ts = encode_single_role(r, tmp, sz, km);
+	else if (abac_role_is_linking(r))
+	    ts = encode_linking_role(r, tmp, sz, km);
 
 	free(r);
-
 	if ( ts < 0 ) 
 	    goto fail;
