<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY RFC1035  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.1035.xml'>
<!ENTITY RFC2119  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml'>
<!ENTITY RFC4648  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4648.xml'>
<!ENTITY RFC4686  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4686.xml'>
<!ENTITY RFC4871  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4871.xml'>
<!ENTITY RFC5234  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.5234.xml'>
<!ENTITY RFC5321  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.5321.xml'>
<!ENTITY RFC5322  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.5322.xml'>
<!ENTITY RFC5617  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.5617.xml'>
<!ENTITY FIPS.180-2.2002  PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml2/reference.FIPS.180-2.2002'>
]>

<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?rfc compact="yes" ?>
<?rfc subcompact="yes" ?>
<?rfc toc="yes" ?>
<?rfc tocindent="yes" ?>
<?rfc symrefs="yes" ?>
<?rfc sortrefs="yes" ?>
<?rfc iprnotified="yes" ?>
<?rfc autobreaks="no"?>
<?rfc strict="yes" ?>

<rfc category="std" docName="draft-otis-dkim-tpa-label-00" ipr="trust200902">
  <front>
    <title abbrev="TPA-Label">DKIM Third-Party Authorization Label</title>

    <author fullname="Douglas Otis" initials="D." surname="Otis">
      <organization>Trend Micro</organization>
      <address>
        <postal>
          <street>10101 N. De Anza Blvd</street>
          <city>Cupertino</city>
          <region>CA</region>
          <code>95014</code>
          <country>USA</country>
        </postal>
        <phone>+1.408.257-1500</phone>
        <email>doug_otis@trendmicro.com</email>
      </address>
    </author>

    <date month="October" year="2009"/>
    <area>Internet Area</area>
    <workgroup>DKIM Working Group</workgroup>
    <keyword>DKIM-TPA-Label</keyword>
    <keyword>Draft</keyword>

    <abstract>
      <t>TPA-label is a DNS-based prefix mechanism for DKIM policy related records as a means to
        authorize Third-Party domains, such as mailing-lists. This mechanism allows first-party
        domains to autonomously authorize a range of third-party domains using scalable, individual
        DNS transactions. This authorization extends the scope of DKIM policy assertions as a means
        to supplant more difficult to administer mechanisms. Alternatives for facilitating
        third-party authorizations currently necessitate coordination between two or more domains to
        synchronously set up selector/key DNS records, DNS zone delegations, or the regular exchange
        of public/private keys.</t>

      <t>Checking DKIM policies may occur when a From header email-address is not within the domain
        of a valid DKIM signature. When a Third-Party signature is found, TPA-Labels offer an
        efficient means for email address domains to authorize specific third-party signing
          domains.<vspace blankLines="1"/></t>
    </abstract>

    <note title="Requirements Language">
      <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
        "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in
          <xref target="RFC2119"/>.</t>
    </note>
  </front>

  <middle>
    <section title="Introduction">
      <t>This document describes how any email-address domain publishing DKIM policy records such as
        those defined in <xref target="RFC5617"/> can also autonomously authorize <xref
          target="RFC4871"/> signing by specific third-party domains. Recommended or suggested
        actions for DKIM receivers are not included, and are considered "out-of-scope" for this
        document. The receiver is assumed to better understand their environment's impact upon the
        performance of DKIM signatures and how results are best utilized.</t>

      <t>TPA-Labels authorize signing domains as a means to permit compliance with DKIM policies
        such those defined by <xref target="RFC5617"/>. TPA-Label authorized domains are to be
        considered equivalent to the authorizing domain for the application of DKIM policies. The
        TXT records associated with these TPA-Labels start with the 'dkim' tag defined by <xref
          target="RFC5617"/> in addition to assertions that are specifically for TPA-Labels as
        defined within this document. This mechanism can eliminate the complex coordination of
        selector/key DNS records, DNS delegation, or exchanges of public/private keys between two or
        more domains that would otherwise be required to facilitate otherwise transparent
        authorizations.</t>

      <t>Trust is an essential requisite before the DKIM signature header field's 'i=' semantics
        provide valuable advisory information. This advisory information is in regard to the
        "on-behalf-of" identity as a means to enable safer message annotations and to better ensure
        trusted identities are recognized. In the case of third-party signatures, the i= value will
        not directly reflect an email-address found witin the From header, but would be in the form
        of an alias.</t>

      <t>TPA-Labels convey which third-party domains are authoritative. Third-party domains are
        unable to utilize DKIM signature's 'i=' semantics to directly assert which identifiers on
        whose behalf a signature was added. As such, no third-party domain should be authorized
        unless it is trusted to ensure that submitting entities have demonstrated receipt of
        messages sent to the From header address contained within message being signed.</t>
    </section>

    <section title="Evaluating Signing Domains">
      <t>Regulatory agencies are unable to control Internet abuse by curtailing access. Unlike IPv4
        addresses, there is virtually no limit on the number of domain-names available. Registrar
        pricing of domain-names need to remain uniform. Otherwise, fees based upon the intrinsic
        value of a name could cause name holders to become extortion targets. High initial costs for
        domain-names are also unlikely to represent a deterrent, largely due to high levels of
        payment fraud.</t>

      <t>In addition, DKIM can not directly identify the domain transmitting the message, and can
        not prevent abusive message replay. Abusive message replay may prove indistinguishable from
        bulk mailings of various types. Since abuse may be beyond the control of the signing domain,
        message acceptance will likely remain dependent upon the reputation of the SMTP client's IP
        address and associated hosts, and perhaps that of the identity represented within the 'i='
        parameter found within the DKIM signature header. Abuse reporting facilitated by DKIM
        signatures should therefore first select signing domains that correspond with domains
        administering the SMTP Client publicly transmitting the message. As such, correspondence
        between the SMTP Client host and the DKIM signing domain might also be affirmed by TPA-Label
        authorizations.</t>

      <t>The receiver's domain evaluation process will confront many domains with unknown
        reputations. New domains are constantly being introduced where registrars are unable to
        prevent bad actors from controlling either a new or previously held domain names. The
        receiver may seek to limit the DKIM verification process, since acquiring policy records or
        DKIM keys may inadvertently leak valuable information that benefit bad actors. Processing
        all DKIM signatures may also inundate a receiver's limited resources. As a result,
        validating DKIM signatures and obtaining related resource records might become limited to
        known trustworthy domains. Signing domains authorized with TPA-Labels by domains having good
        reputations might then provide a means to safely extend limited verification resources.</t>
    </section>

    <section title="Authorization Scope">
      <t>Without using TPA-Labels, an authorization effort will likely involve sharing details
        between the domain owner, and one or more email and DNS providers. Since there are many ways
        in which such authorizations can be accomplished, it is unlikely there will be consistent or
        standardized formats developed to exchange necessary, and at times, sensitive information.
        In addition, when there is a security breach, the wrong party might be held accountable for
        content they may have never seen nor logged. The TPA-Label authorization scheme permits the
        content of the DKIM signature header to clarify who signed the message and on whose behalf,
        while also permitting greater control by the authorizing domain.</t>

      <t>TPA-Label resource records replace domain delegations, selector/key record mirroring, or
        key exchanges. Significant amounts of detail is associated with selector/key records. These
        details include user limitations, suitable services, key resource record's Time-To-Live,
        revocation and update procedures, and how the DKIM Signature header field's 'i=' semantics
        are to be applied. The TPA-Labeled policy records allow authorizing domains an improved
        ability to limit the scope of their authorizations, without being mistaken for having
        authenticated the entity submitting the message.</t>

      <t>When a signing domain differs from that of a domain within the header email-address,
        TPA-Label resource records safely extend policy compliance where DNS publication is only
        required by the email-address domain even when signing domains and the email-address domains
        differ. While offering only valid signatures will not ensure all possible spoofing is
        prevented, messages signed in this manner should not receive annotations indicating there
        are authenticated identities either. Authorizing domains to play the role of only providing
        acceptable signatures may be suitable for non-critical messages, where the goal might be to
        improve delivery acceptance, such as those from mailing-lists.</t>
    </section>

    <section title="TPA-Label Tag Definitions">
      <t>Every TPA-Label TXT resource record MUST start with an outbound signing-practices tag, so
        the first four characters of the record are lowercase "dkim", followed by optional
        whitespace and "=". In addition to tags defined by <xref target="RFC5617"/>, TPA-Label
        syntax descriptions use the form described in Augmented BNF for Syntax Specifications <xref
          target="RFC5234"/>. The "base32" function is defined in <xref target="RFC4648"/> and the
        "sha-1" hash function is defined in <xref target="FIPS.180-2.2002"/>. The TPA-Label TXT
        resource records follow the tag-value syntax described in section 4.2.1 of <xref
          target="RFC5617"/> and section 3.2 of <xref target="RFC4871"/>. Unrecognized tags and tags
        with illegal values MUST be ignored. In the ABNF below, the WSP token is inherited from
          <xref target="RFC5322"/>. The ALPHA and DIGIT tokens are imported from <xref
          target="RFC5234"/>. The function "lcase" converts upper-case ALPHA characters to
        lower-case. The function "sha-1" returns a hash that is converted to a base32 character set.
        The terminating period is not included in domain-name conversions. In addition, a newline
        character (0x0A) is appended to the end of the string to match a command line generation of
        SHA1 values. The tags used in TPA-Labeled policy records are as follows:</t>
      <figure title="">
        <artwork name="" type="" height="" width="" xml:space="preserve">
  asterisk = %x2A ; "*"
  dash = %x2D ; "-"
  dot = %x2E ; "."
  underscore = %x5F ; "_"
  ANY = asterisk dot ; "*."
  dns-char = ALPHA / DIGIT / dash
  id-prefix = ALPHA / DIGIT
  label = id-prefix [*61dns-char id-prefix]
  sldn = label dot label
  base-char = (dns-char / underscore)
  domain = *(label dot) sldn
  tpa-label = underscore base32( sha-1( lcase(signing-domain))) 
    </artwork>
      </figure>
      <texttable title="TPA-Label Extended Parameters">
        <ttcol align="center">Tag</ttcol>
        <ttcol align="left">Function</ttcol>
        <c>scope=</c>
        <c>Authorization Scope List (as-list)</c>
        <!--  -->
        <c>tpa=</c>
        <c>Authorized Domains List (ad-list)</c>
        <!--  -->
      </texttable>

      <texttable title="TPA-Label Scope Values">
        <ttcol align="left" width="10%">Scope Values</ttcol>
        <ttcol align="left">Field or Parameter</ttcol>
        <c>F</c>
        <c>From (Author) Header</c>
        <!--  -->
        <c>O</c>
        <c>Other than From (Author) Headers</c>
        <!--  -->
        <c>M</c>
        <c>MailFrom</c>
        <!--  -->
        <c>H</c>
        <c>SMTP Host</c>
        <!--  -->
        <c>NO-TPA</c>
        <c>All</c>
        <!--  -->
      </texttable>

      <t>The receiver obtains the TPA-Label record for the email-address domain using a DNS query
        for an IN class TXT resource record. The TPA-Label is created by processing the domain found
        within the signature's "d=" parameter (does not include the trailing period). The TPA-Label
        would be placed below the normal policy records, for example
        "._adsp.domainkey.&lt;email-address domain&gt;". These labels would then be used to
        access the TPA-Labeled policy TXT records. Character-strings contained within the TXT
        resource record are concatenated into forming a single string. A character-string is a
        single length octet followed by that number of characters treated as binary information. As
        an example, a TPA-Labeled policy record may be located at these domains:<list>
          <t/>
          <t>&lt;tpa-label&gt;._adsp._domainkey.&lt;email-address domain&gt;.</t>
        </list>
        <vspace blankLines="1"/></t>
    </section>

    <section title="Scope">
      <t>scope= Authorization Scope List (Optional). This tag defines a list of scoping assertions
        for various email-address locations within the message.</t>
      <t>
        <list>
          <t>scope = "F" / "O" / "M" / "H" / "NO-TPA"</t>
          <t>as-list = "scope" [WSP] "=" [WSP] scope 0*([WSP] ":" [WSP] scope)</t>
        </list>
      </t>

      <section title="From (Author) Header Field">
        <t>The "F" scope asserts that messages carrying the email-address domain within the From
          header field are authorized to be signed by the tpa listed domain.<vspace blankLines="1"
          /></t>
      </section>

      <section title="MailFrom Parameter">
        <t>This "M" scope asserts that messages carrying the email-address domain within the
          MailFrom parameter are also authorized to be signed by the authorized domain.<vspace
            blankLines="1"/></t>
      </section>

      <section title="Other Originating Header Fields">
        <t>The "O" scope asserts that messages carrying the email-address domain within the Sender
          or Resent-* header fields are authorized to be signed by the authorized domain.<vspace
            blankLines="1"/></t>
      </section>

      <section title="SMTP Host domains">
        <t>The "H" scope asserts that messages transmitted by SMTP hosts have been authorized. This
          scope might be used to better ensure DKIM signatures are validated.<vspace blankLines="1"
          /></t>
      </section>

      <section title="NO-TPA">
        <t>The "NO-TPA" scope asserts that domain does not publish TPA-Labeled policy
            records.<vspace blankLines="1"/></t>
      </section>
    </section>

    <section title="Authorized Signing Domain">
      <t>tpa= Authorized Signing Domain list (Optional). This tag repeats all or portions of the
        domain encoded within the TPA-Label. This option ensures proper handling of possible hash
        collisions. When a domain is prefixed with the "*." ANY label, then all subdomains of this
        domain are to be considered included within the list.</t>
      <t>
        <list>
          <t>ad = [ANY] domain</t>
          <t>ad-list = "tpa" [WSP] "=" [WSP] ad 0*([WSP] ":" [WSP] ad)</t>
          <t>
            <vspace blankLines="1"/>
          </t>
        </list>
      </t>
    </section>

    <section title="Use of TPA-Label Resource Records">
      <t>Use of TPA-Label resource record assertions need not be are subsequent to the discovery of
        the policy record specified by <xref target="RFC5617"/>. When an acceptable First-Party
        signature was not discovered, and the From domain's <xref target="RFC5617"/> resource record
        contains the "scope" tag then:</t>
      <t>
        <list>
          <t>When one or more valid Third-Party Signatures are present in the message, and a scope
            tag exists within the normal policy record, and the scope tag does not contain "NO-TPA",
              then:<list style="symbols">

              <t>When a TPA-Label TXT resource record within the From header domain has a scope tag
                of "F" and the email-address domain within the From headers is within the
                authorizing domain, then the message is considered signed with an Author's Domain
                Acceptable Third-Party Signature.</t>

              <t>When a TPA-Label TXT resource record within the From header domain has a scope tag
                of "O" and the email-address domain within the Sender, or Resent-* headers are
                within the authorizing domain, then the message is considered signed with an
                Author's Domain Acceptable Third-Party Signature.</t>

              <t>When no TPA-Label TXT resource record is found or published, and a valid
                Third-party signature is acceptable to the verifier, then the message is considered
                signed by a Verifier Acceptable Third-Party Signature.</t>
            </list></t>
        </list>
      </t>
    </section>

    <section anchor="IANA" title="IANA Considerations">
      <t>A registry has been established for DKIM policy record tags for RFC5617 which will need
        updated with the tags "tpa" and "scope".</t>
      <t>Note to RFC Editor: this section may be removed on publication as an RFC.</t>
    </section>

    <section anchor="Security" title="Security Considerations">
      <t>This draft extends signing policies related to <xref target="RFC4871"/>. Security
        considerations are mostly related to attempts on the part of malicious senders to represent
        themselves as other senders, often in an attempt to defraud either the recipient or the
        alleged originator. Additional security considerations regarding DKIM signing practices may
        be found in the DKIM threat analysis <xref target="RFC4686"/>.</t>
      <t>The use of the SHA-1 hash algorithm does not represent a security concern. The hash simply
        ensures a deterministic domain-name size is achieved. Unexpected collisions can be detected
        and handled by using the extended TPA-Label "tpa=" option.<vspace blankLines="100"/></t>
    </section>

    <section anchor="Acknowledgements" title="Acknowledgements">
      <t>Frank Ellermann and Wietse Venema.<vspace blankLines="5"/></t>
    </section>
  </middle>

  <back>
    <references title="Normative References"> &RFC2119; &RFC4648; &RFC4871;
      &RFC5234; &RFC5321; &RFC5322; &RFC5617; &FIPS.180-2.2002; </references>

    <references title="Informative References"> &RFC4686; </references>

    <section title="DNS Example of TPA-Label policy record placement" toc="default">
      <figure title="">
        <artwork name="" type="" height="" width="" xml:space="preserve">
 ####          
 # Policies for Example.com email domain using example.com, isp.com,
 # and example.com.isp.com as signing domains.
 ####

 #### 5322.From authorization for TP domains ####
                                _adsp._domainkey.example.com.  IN TXT 
    "dkim=all; scope=F:O:M;"

 ## "isp.com" TPA-Label ##
 _HGSSD3SNMI6635J5743VDJHAJKMPMFIF._adsp._domainkey.example.com. IN TXT
    "dkim=all; tpa=isp.com; scope=F;"

 #### 5322.From/Originator/MailFrom authorization for TP domains ####

 ## "example.com.isp.com" TPA-Label ##
 _ZZHFFXWCFI7RPDDQDIGYHPBTAA7VWITU._adsp._domainkey.example.com.  IN TXT
    "dkim=all; tpa=*.isp.com; scope=F:O:M;" 
        </artwork>
      </figure>
      <t>
        <vspace blankLines="100"/>
      </t>
    </section>
    <section title="C code for label generation">
      <t>The following utility can be compiled as tpa-label.c using the following:</t>
      <t>gcc -lcrypto tpa-label.c -o tpa-label</t>
      <figure title="">
        <artwork name="" type="" height="" width="" xml:space="preserve">
/*
 * TPA-Label generation utility 
 * Copyright (C) 2009 The IETF Trust &amp; and the persons identified as
 * the document authors.  All rights reserved.
 * Redistributions of source code must retain the above copyright
 * notice and the following disclaimer.
 *
 * This document is subject to the rights, licenses and restrictions
 * contained in BCP 78, and except as set forth therein, the authors
 * retain all their rights.
 * This document and the information contained herein are provided on an
 * "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
 * OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
 * THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
 * THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
 * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 */

#include &lt;stdio.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;stddef.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;ctype.h&gt;
#include &lt;unistd.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;errno.h&gt;
#include &lt;openssl/sha.h&gt;

#define TPA_LABEL_VERSION   100
#define MAX_DOMAIN_NAME     256
#define MAX_FILE_NAME       1024
                                
static char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
static char sign_on[] =
{"%s v%d.%02d Copyright (C) (2009) The IETF Trust &amp; Douglas Otis\n"};
char err_cmd[] =\
 "ERR: Command error with [%s]\n";
char use_txt[]=\
 "Usage: TPA-Label [-i domain_input_file] [-o label_output_file][-v]\n";
char help_txt[]=\
"The options are as follows:\n"\
"-i  domain name input. Defaults to stdin. Removes trailing '.'\n"\
"-o  TPA-Label output.  Defaults to stdout.\n"\
"-v  Specifies Verbose Mode.\n\n";

static void usage(void);
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

static void
usage(void)
{
    (void) fprintf(stderr, "\n%s%s", use_txt, help_txt);
    exit(1);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

int 
main (int argc, char * argv[])
{
    int  ret_val, in_mode, out_mode, verbose, done, i, j, k;
    char ch;
    unsigned long len;
    unsigned long long b_5;
    char in_fn[MAX_FILE_NAME], out_fn[MAX_FILE_NAME];
    unsigned char in_buf[MAX_DOMAIN_NAME + 2];
    unsigned char sha_res[20], tpa_label[33];
    FILE *in_file, *out_file;

    ret_val = in_mode = out_mode = verbose = done = 0;
    len = 0;

    while ((ch = getopt(argc, argv, "i:o:v")) != -1)
    {
        switch (ch) 
        {
            case 'i':
                in_mode = 1;          /* input from file */
                (void) strncpy(in_fn, optarg, sizeof(in_fn));
                in_fn[sizeof(in_fn) - 1] = '\0';
                break;
            case 'o':
                 out_mode = 1;         /* out to time */
                 (void) strncpy(out_fn, optarg, sizeof(out_fn));
                 out_fn[sizeof(out_fn) - 1] = '\0';
                 break;
            case 'v':
                 verbose = 1;
                 break;
            case '?':
            default:
                (void) usage();
                break;
        }
    };

    if (in_mode)
    {
        if ((in_file = fopen(in_fn, "r")) == NULL)
        {
            (void) fprintf(stderr,
                           "ERR: Error opening [%s] input file.\n",
                           in_fn);
            exit(2);
        }
    }
    else
    {
        in_file = stdin;
    }

    if (out_mode)
    {
        if ((out_file = fopen(out_fn, "w")) == NULL)
        {
            (void) fprintf(stderr, 
                           "ERR: Error opening [%s] output file.\n",
                           out_fn);
            exit(3);
        }
    }
    else
    {
        out_file = stdout;
    }

    if (out_mode &amp;&amp; verbose)
    {
        (void) printf(sign_on, "tpa-label utility",
                      TPA_LABEL_VERSION / 100,
                      TPA_LABEL_VERSION % 100);
    }

    for (i = 0; i &lt; MAX_DOMAIN_NAME &amp;&amp; !done; i++)
    {
        if ((ch = fgetc(in_file)) == EOF)
        {
            ch = 0;
        }
        else  if (ch == '\n' || ch == '\r')
        {
            ch = 0;
        }

        in_buf[i] = tolower(ch);

        if (ch == 0) 
        {
            len = i;         /* string length */
            done = 1;     
        }
    }

    if (!done)
    {
        (void) fprintf(stderr, "ERR: Domain name too long.\n");
        exit (4);
    }

    if (len &amp;&amp; in_buf[len - 1] == '.')    /* remove any trailing "." */
    {
        len--;
        in_buf[len] = 0;     /* replace trailing "." with 0 */
    }

    in_buf[len++] = '\n';    /* newline simulates commmand-line use */
    in_buf[len] = 0;         /* terminate string */  
                                
    if (len &lt; 2)
    {
        (void) 
        fprintf(stderr,
                "ERR: Domain name [%s] too short with %d length.\n",
                in_buf,
                len);
        exit (5);
    }

    SHA1(in_buf, len, sha_res);

    if (verbose)
    {
        printf("Normalized Domain = [%s] %d, SHA-1 = ", in_buf, len);

        for (i = 0; i &lt; 20; i++)
        {
            printf("%02X", sha_res[i]);
        }
        printf("\nTPA-Label: 5 bit intervals left to right.\n");
    }

    /* process sha-1 results 4 times by 40 bits 0 to 160 */

    for (i = 0, j = 0; i &lt; 4 ; i++)         
    {
        b_5 =  (unsigned long long) sha_res[(i * 5)] &lt;&lt; 32;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 1] &lt;&lt; 24;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 2] &lt;&lt; 16;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 3] &lt;&lt; 8;
        b_5 |= (unsigned long long) sha_res[(i * 5) + 4];
 
        if (verbose)
        {
            printf(" {%010llX}-&gt;", b_5);
        }

        for (k = 35; k &gt;= 0; k-= 5, j++)    /* convert 40 bits (5x8) */
        {
            tpa_label[j] = base32[(b_5 &gt;&gt; k) &amp; 0x1F];

            if (verbose)
            {
                 printf(" %02X:%c", 
                        (unsigned int)(b_5 &gt;&gt; k) &amp; 0x1F,
                        tpa_label[j]);
            }
        }
        if (verbose)
        {
            printf ("\n");
        }
    }
    if (verbose)
    {
        printf("\n");
    }

    tpa_label[j] = 0;   /* terminate label string */
    fprintf(out_file, "_%s", tpa_label);
    printf("\n");

    /* close */
    if (out_mode)
    {
        if (fclose (out_file) != 0)
        {
            (void) fprintf(stderr,
                           "ERR: Unable to close %s output file.\n",
                           out_fn);
            ret_val = 6;
        }
    }
    if (in_mode)
    {
        if (fclose (in_file) != 0)
        {
            (void) fprintf(stderr,
                           "ERR: Unable to close %s input file.\n",
                           in_fn);
             ret_val = 7;
        }
    }
    return (ret_val);
}
        </artwork>
      </figure>
    </section>
  </back>
</rfc>

