Back to index

lightning-sunbird  0.9+nobinonly
Functions
pk7print.c File Reference
#include "secutil.h"
#include "secpkcs7.h"
#include "secoid.h"
#include <sys/stat.h>
#include <stdarg.h>
#include "cert.h"
#include "prtypes.h"
#include "prtime.h"
#include "prlong.h"
#include "secmod.h"
#include "pk11func.h"
#include "prerror.h"

Go to the source code of this file.

Functions

int sv_PrintPKCS7ContentInfo (FILE *, SEC_PKCS7ContentInfo *, char *)
void sv_PrintAsHex (FILE *out, SECItem *data, char *m)
void sv_PrintInteger (FILE *out, SECItem *i, char *m)
int sv_PrintTime (FILE *out, SECItem *t, char *m)
int sv_PrintValidity (FILE *out, CERTValidity *v, char *m)
void sv_PrintObjectID (FILE *out, SECItem *oid, char *m)
void sv_PrintAlgorithmID (FILE *out, SECAlgorithmID *a, char *m)
void sv_PrintAttribute (FILE *out, SEC_PKCS7Attribute *attr, char *m)
void sv_PrintName (FILE *out, CERTName *name, char *msg)
void sv_PrintSignerInfo (FILE *out, SEC_PKCS7SignerInfo *info, char *m)
void sv_PrintRSAPublicKey (FILE *out, SECKEYPublicKey *pk, char *m)
void sv_PrintDSAPublicKey (FILE *out, SECKEYPublicKey *pk, char *m)
int sv_PrintSubjectPublicKeyInfo (FILE *out, PRArenaPool *arena, CERTSubjectPublicKeyInfo *i, char *msg)
SECStatus sv_PrintInvalidDateExten (FILE *out, SECItem *value, char *msg)
int sv_PrintExtensions (FILE *out, CERTCertExtension **extensions, char *msg)
void sv_PrintCRLInfo (FILE *out, CERTCrl *crl, char *m)
int sv_PrintCertificate (FILE *out, SECItem *der, char *m, int level)
int sv_PrintSignedData (FILE *out, SECItem *der, char *m, SECU_PPFunc inner)
int sv_PrintPKCS7Signed (FILE *out, SEC_PKCS7SignedData *src)
int SV_PrintPKCS7ContentInfo (FILE *out, SECItem *der)

Function Documentation

void sv_PrintAlgorithmID ( FILE out,
SECAlgorithmID *  a,
char *  m 
)

Definition at line 165 of file pk7print.c.

{
    sv_PrintObjectID(out, &a->algorithm, m);

    if ((a->parameters.len != 2) ||
        (PORT_Memcmp(a->parameters.data, "\005\000", 2) != 0)) {
        /* Print args to algorithm */
        sv_PrintAsHex(out, &a->parameters, "Args=");
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sv_PrintAsHex ( FILE out,
SECItem *  data,
char *  m 
)

Definition at line 78 of file pk7print.c.

{
    unsigned i;

    if (m) fprintf(out, m);
    
    for (i = 0; i < data->len; i++) {
        if (i < data->len - 1) {
            fprintf(out, "%02x:", data->data[i]);
        } else {
            fprintf(out, "%02x\n", data->data[i]);
            break;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sv_PrintAttribute ( FILE out,
SEC_PKCS7Attribute *  attr,
char *  m 
)

Definition at line 177 of file pk7print.c.

{
    SECItem *value;
    int i;
    char om[100];

    fprintf(out, m);

    /*
     * XXX Make this smarter; look at the type field and then decode
     * and print the value(s) appropriately!
     */
    sv_PrintObjectID(out, &(attr->type), "type=");
    if (attr->values != NULL) {
        i = 0;
        while ((value = attr->values[i]) != NULL) {
            sprintf(om, "%svalue[%d]=%s", m, i++, attr->encoded ? "(encoded)" : ""); 
            if (attr->encoded || attr->typeTag == NULL) {
                sv_PrintAsHex(out, value, om);
            } else {
                switch (attr->typeTag->offset) {
                    default:
                        sv_PrintAsHex(out, value, om);
                        break;
                    case SEC_OID_PKCS9_CONTENT_TYPE:
                        sv_PrintObjectID(out, value, om);
                        break;
                    case SEC_OID_PKCS9_SIGNING_TIME:
                        sv_PrintTime(out, value, om);
                        break;
                }
            }
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sv_PrintCertificate ( FILE out,
SECItem *  der,
char *  m,
int  level 
)

Definition at line 483 of file pk7print.c.

{
    PRArenaPool *arena = NULL;
    CERTCertificate *c;
    int rv;
    int iv;
    char mm[200];
    
    /* Decode certificate */
    c = (CERTCertificate*) PORT_ZAlloc(sizeof(CERTCertificate));
    if (!c) return PORT_GetError();

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena) return SEC_ERROR_NO_MEMORY;

    rv = SEC_ASN1DecodeItem(arena, c, CERT_CertificateTemplate, der);
    if (rv) {
        PORT_FreeArena(arena, PR_FALSE);
        return rv;
    }

    /* Pretty print it out */
    iv = DER_GetInteger(&c->version);
    fprintf(out, "%sversion=%d (0x%x)\n", m, iv + 1, iv);
    sprintf(mm, "%sserialNumber=", m);
    sv_PrintInteger(out, &c->serialNumber, mm);
    sprintf(mm, "%ssignatureAlgorithm=", m);
    sv_PrintAlgorithmID(out, &c->signature, mm);
    sprintf(mm, "%sissuerName=", m);
    sv_PrintName(out, &c->issuer, mm);
    sprintf(mm, "%svalidity.", m);
    sv_PrintValidity(out, &c->validity, mm);
    sprintf(mm, "%ssubject=", m);
    sv_PrintName(out, &c->subject, mm);
    sprintf(mm, "%ssubjectPublicKeyInfo", m);
    rv = sv_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo, mm);
    if (rv) {
        PORT_FreeArena(arena, PR_FALSE);
        return rv;
    }
    sprintf(mm, "%ssignedExtensions.", m);
    sv_PrintExtensions(out, c->extensions, mm);
    
    PORT_FreeArena(arena, PR_FALSE);
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sv_PrintCRLInfo ( FILE out,
CERTCrl *  crl,
char *  m 
)

Definition at line 451 of file pk7print.c.

{
    CERTCrlEntry *entry;
    int iv;
    char om[100];
    
    fprintf(out, m);
    sv_PrintAlgorithmID(out, &(crl->signatureAlg), "signatureAlgorithm=");
    fprintf(out, m);
    sv_PrintName(out, &(crl->name), "name=");
    fprintf(out, m);
    sv_PrintTime(out, &(crl->lastUpdate), "lastUpdate=");
    fprintf(out, m);
    sv_PrintTime(out, &(crl->nextUpdate), "nextUpdate=");
    
    if (crl->entries != NULL) {
        iv = 0;
        while ((entry = crl->entries[iv]) != NULL) {
            fprintf(out, "%sentry[%d].", m, iv); 
            sv_PrintInteger(out, &(entry->serialNumber), "serialNumber=");
            fprintf(out, "%sentry[%d].", m, iv); 
            sv_PrintTime(out, &(entry->revocationDate), "revocationDate=");
            sprintf(om, "%sentry[%d].signedCRLEntriesExtensions.", m, iv++); 
            sv_PrintExtensions(out, entry->extensions, om);
        }
    }
    sprintf(om, "%ssignedCRLEntriesExtensions.", m); 
    sv_PrintExtensions(out, crl->extensions, om);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sv_PrintDSAPublicKey ( FILE out,
SECKEYPublicKey *  pk,
char *  m 
)

Definition at line 335 of file pk7print.c.

{
    fprintf(out, m);
    sv_PrintInteger(out, &pk->u.dsa.params.prime, "prime=");
    fprintf(out, m);
    sv_PrintInteger(out, &pk->u.dsa.params.subPrime, "subprime=");
    fprintf(out, m);
    sv_PrintInteger(out, &pk->u.dsa.params.base, "base=");
    fprintf(out, m);
    sv_PrintInteger(out, &pk->u.dsa.publicValue, "publicValue=");
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sv_PrintExtensions ( FILE out,
CERTCertExtension **  extensions,
char *  msg 
)

Definition at line 410 of file pk7print.c.

{
    SECOidTag oidTag;

    if (extensions) {

        while ( *extensions ) {
            SECItem *tmpitem;

            fprintf(out, "%sname=", msg);

            tmpitem = &(*extensions)->id;
            sv_PrintObjectID(out, tmpitem, NULL);

            tmpitem = &(*extensions)->critical;
            if ( tmpitem->len )
                fprintf(out, "%scritical=%s\n", msg,
                        (tmpitem->data && tmpitem->data[0])? "True": "False");

            oidTag = SECOID_FindOIDTag (&((*extensions)->id));

            fprintf(out, msg);
            tmpitem = &((*extensions)->value);
            if (oidTag == SEC_OID_X509_INVALID_DATE) 
                sv_PrintInvalidDateExten (out, tmpitem,"invalidExt");
            else                       
                sv_PrintAsHex(out,tmpitem, "data=");

            /*fprintf(out, "\n");*/
            extensions++;
        }
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sv_PrintInteger ( FILE out,
SECItem *  i,
char *  m 
)

Definition at line 95 of file pk7print.c.

{
    int iv;

    if (i->len > 4) {
        sv_PrintAsHex(out, i, m);
    } else {
        iv = DER_GetInteger(i);
        fprintf(out, "%s%d (0x%x)\n", m, iv, iv);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus sv_PrintInvalidDateExten ( FILE out,
SECItem *  value,
char *  msg 
)

Definition at line 386 of file pk7print.c.

{
    SECItem decodedValue;
    SECStatus rv;
    int64 invalidTime;
    char *formattedTime = NULL;

    decodedValue.data = NULL;
    rv = SEC_ASN1DecodeItem (NULL, &decodedValue, SEC_GeneralizedTimeTemplate,
                             value);
    if (rv == SECSuccess) {
        rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
        if (rv == SECSuccess) {
            formattedTime = CERT_GenTime2FormattedAscii(invalidTime, "%a %b %d %H:%M:%S %Y");
            fprintf (out, "%s: %s\n", msg, formattedTime);
            PORT_Free (formattedTime);
        }
    }
    PORT_Free (decodedValue.data);

    return (rv);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sv_PrintName ( FILE out,
CERTName *  name,
char *  msg 
)

Definition at line 214 of file pk7print.c.

{
    char *str;

    str = CERT_NameToAscii(name);
    fprintf(out, "%s%s\n", msg, str);
    PORT_Free(str);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sv_PrintObjectID ( FILE out,
SECItem *  oid,
char *  m 
)

Definition at line 147 of file pk7print.c.

{
    const char *name;
    SECOidData *oiddata;
    
    oiddata = SECOID_FindOID(oid);
    if (oiddata == NULL) {
        sv_PrintAsHex(out, oid, m);
        return;
    }
    name = oiddata->desc;

    if (m != NULL)
        fprintf(out, "%s", m);
    fprintf(out, "%s\n", name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sv_PrintPKCS7ContentInfo ( FILE out,
SEC_PKCS7ContentInfo *  src,
char *  m 
)

Definition at line 816 of file pk7print.c.

{
    const char *desc;
    SECOidTag kind;
    int rv;

    if (src->contentTypeTag == NULL)
        src->contentTypeTag = SECOID_FindOID(&(src->contentType));

    if (src->contentTypeTag == NULL) {
        desc = "Unknown";
        kind = SEC_OID_PKCS7_DATA;
    } else {
        desc = src->contentTypeTag->desc;
        kind = src->contentTypeTag->offset;
    }

    fprintf(out, "%s%s\n", m, desc);

    if (src->content.data == NULL) {
        fprintf(out, "pkcs7.data=<no content>\n");
        return 0;
    }

    rv = 0;
    switch (kind) {
        case SEC_OID_PKCS7_SIGNED_DATA:  /* Signed Data */
            rv = sv_PrintPKCS7Signed(out, src->content.signedData);
            break;

        case SEC_OID_PKCS7_ENVELOPED_DATA:  /* Enveloped Data */
            fprintf(out, "pkcs7EnvelopedData=<unsupported>\n");
            /*sv_PrintPKCS7Enveloped(out, src->content.envelopedData);*/
            break;

        case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:  /* Signed and Enveloped */
            fprintf(out, "pkcs7SignedEnvelopedData=<unsupported>\n");
            /*rv = sv_PrintPKCS7SignedAndEnveloped(out,
                                src->content.signedAndEnvelopedData);*/
            break;

        case SEC_OID_PKCS7_DIGESTED_DATA:  /* Digested Data */
            fprintf(out, "pkcs7DigestedData=<unsupported>\n");
            /*sv_PrintPKCS7Digested(out, src->content.digestedData);*/
            break;

        case SEC_OID_PKCS7_ENCRYPTED_DATA:  /* Encrypted Data */
            fprintf(out, "pkcs7EncryptedData=<unsupported>\n");
            /*sv_PrintPKCS7Encrypted(out, src->content.encryptedData);*/
            break;

        default:
            fprintf(out, "pkcs7UnknownData=<unsupported>\n");
            /*sv_PrintAsHex(out, src->content.data);*/
            break;
    }

    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int SV_PrintPKCS7ContentInfo ( FILE out,
SECItem *  der 
)

Definition at line 878 of file pk7print.c.

{
    SEC_PKCS7ContentInfo *cinfo;
    int rv = -1;

    cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

    if (cinfo != NULL) {
        rv = sv_PrintPKCS7ContentInfo(out, cinfo, "pkcs7.contentInfo=");
        SEC_PKCS7DestroyContentInfo(cinfo);
    }

    return rv;
}

Here is the caller graph for this function:

int sv_PrintPKCS7Signed ( FILE out,
SEC_PKCS7SignedData *  src 
)

Definition at line 577 of file pk7print.c.

{
    SECAlgorithmID *digAlg;        /* digest algorithms */
    SECItem *aCert;                /* certificate */
    CERTSignedCrl *aCrl;           /* certificate revocation list */
    SEC_PKCS7SignerInfo *sigInfo;  /* signer information */
    int rv, iv;
    char om[120];

    sv_PrintInteger(out, &(src->version), "pkcs7.version=");

    /* Parse and list digest algorithms (if any) */
    if (src->digestAlgorithms != NULL) {
        iv = 0;
        while (src->digestAlgorithms[iv] != NULL)
            iv++;
        fprintf(out, "pkcs7.digestAlgorithmListLength=%d\n", iv);
        iv = 0;
        while ((digAlg = src->digestAlgorithms[iv]) != NULL) {
            sprintf(om, "pkcs7.digestAlgorithm[%d]=", iv++);
            sv_PrintAlgorithmID(out, digAlg, om);
        }
    }

    /* Now for the content */
    rv = sv_PrintPKCS7ContentInfo(out, &(src->contentInfo), 
                                                "pkcs7.contentInformation=");
    if (rv != 0) return rv;

    /* Parse and list certificates (if any) */
    if (src->rawCerts != NULL) {
        iv = 0;
        while (src->rawCerts[iv] != NULL)
            iv++;
        fprintf(out, "pkcs7.certificateListLength=%d\n", iv);

        iv = 0;
        while ((aCert = src->rawCerts[iv]) != NULL) {
            sprintf(om, "certificate[%d].", iv++);
            rv = sv_PrintSignedData(out, aCert, om, sv_PrintCertificate);
            if (rv) return rv;
        }
    }

    /* Parse and list CRL's (if any) */
    if (src->crls != NULL) {
        iv = 0;
        while (src->crls[iv] != NULL) iv++;
        fprintf(out, "pkcs7.signedRevocationLists=%d\n", iv);
        iv = 0;
        while ((aCrl = src->crls[iv]) != NULL) {
            sprintf(om, "signedRevocationList[%d].", iv);
            fprintf(out, om);
            sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm, 
                                "signatureAlgorithm=");
            DER_ConvertBitString(&aCrl->signatureWrap.signature);
            fprintf(out, om);
            sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "signature=");
            sprintf(om, "certificateRevocationList[%d].", iv);
            sv_PrintCRLInfo(out, &aCrl->crl, om);
            iv++;
        }
    }

    /* Parse and list signatures (if any) */
    if (src->signerInfos != NULL) {
        iv = 0;
        while (src->signerInfos[iv] != NULL)
            iv++;
        fprintf(out, "pkcs7.signerInformationListLength=%d\n", iv);
        iv = 0;
        while ((sigInfo = src->signerInfos[iv]) != NULL) {
            sprintf(om, "signerInformation[%d].", iv++);
            sv_PrintSignerInfo(out, sigInfo, om);
        }
    }  

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sv_PrintRSAPublicKey ( FILE out,
SECKEYPublicKey *  pk,
char *  m 
)

Definition at line 326 of file pk7print.c.

{
    fprintf(out, m);
    sv_PrintInteger(out, &pk->u.rsa.modulus, "modulus=");
    fprintf(out, m);
    sv_PrintInteger(out, &pk->u.rsa.publicExponent, "exponent=");
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sv_PrintSignedData ( FILE out,
SECItem *  der,
char *  m,
SECU_PPFunc  inner 
)

Definition at line 531 of file pk7print.c.

{
    PRArenaPool *arena = NULL;
    CERTSignedData *sd;
    int rv;

    /* Strip off the signature */
    sd = (CERTSignedData*) PORT_ZAlloc(sizeof(CERTSignedData));
    if (!sd) return PORT_GetError();

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena) return SEC_ERROR_NO_MEMORY;

    rv = SEC_ASN1DecodeItem(arena, sd, CERT_SignedDataTemplate, der);
    if (rv) {
        PORT_FreeArena(arena, PR_FALSE);
        return rv;
    }

/*    fprintf(out, "%s:\n", m); */
    PORT_Strcat(m, "data.");

    rv = (*inner)(out, &sd->data, m, 0);
    if (rv) {
        PORT_FreeArena(arena, PR_FALSE);
        return rv;
    }

    m[PORT_Strlen(m) - 5] = 0;
    fprintf(out, m);
    sv_PrintAlgorithmID(out, &sd->signatureAlgorithm, "signatureAlgorithm=");
    DER_ConvertBitString(&sd->signature);
    fprintf(out, m);
    sv_PrintAsHex(out, &sd->signature, "signature=");

    PORT_FreeArena(arena, PR_FALSE);
    return 0;

}

Here is the call graph for this function:

Here is the caller graph for this function:

void sv_PrintSignerInfo ( FILE out,
SEC_PKCS7SignerInfo *  info,
char *  m 
)

Definition at line 275 of file pk7print.c.

{
    SEC_PKCS7Attribute *attr;
    int iv;
    
    fprintf(out, m);
    sv_PrintInteger(out, &(info->version), "version=");

    fprintf(out, m);
    sv_PrintName(out, &(info->issuerAndSN->issuer), "issuerName=");
    fprintf(out, m);
    sv_PrintInteger(out, &(info->issuerAndSN->serialNumber), 
                        "serialNumber=");
  
    fprintf(out, m);
    sv_PrintAlgorithmID(out, &(info->digestAlg), "digestAlgorithm=");
    
    if (info->authAttr != NULL) {
        char mm[120];

        iv = 0;
        while (info->authAttr[iv] != NULL) iv++;
        fprintf(out, "%sauthenticatedAttributes=%d\n", m, iv);
        iv = 0;
        while ((attr = info->authAttr[iv]) != NULL) {
            sprintf(mm, "%sattribute[%d].", m, iv++); 
            sv_PrintAttribute(out, attr, mm);
        }
    }
    
    /* Parse and display signature */
    fprintf(out, m);
    sv_PrintAlgorithmID(out, &(info->digestEncAlg), "digestEncryptionAlgorithm=");
    fprintf(out, m);
    sv_PrintAsHex(out, &(info->encDigest), "encryptedDigest=");
    
    if (info->unAuthAttr != NULL) {
        char mm[120];

        iv = 0;
        while (info->unAuthAttr[iv] != NULL) iv++;
        fprintf(out, "%sunauthenticatedAttributes=%d\n", m, iv);
        iv = 0;
        while ((attr = info->unAuthAttr[iv]) != NULL) {
            sprintf(mm, "%sattribute[%d].", m, iv++); 
            sv_PrintAttribute(out, attr, mm);
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sv_PrintSubjectPublicKeyInfo ( FILE out,
PRArenaPool arena,
CERTSubjectPublicKeyInfo *  i,
char *  msg 
)

Definition at line 348 of file pk7print.c.

{
    SECKEYPublicKey *pk;
    int rv;
    char mm[200];

    sprintf(mm, "%s.publicKeyAlgorithm=", msg);
    sv_PrintAlgorithmID(out, &i->algorithm, mm);

    pk = (SECKEYPublicKey*) PORT_ZAlloc(sizeof(SECKEYPublicKey));
    if (!pk) return PORT_GetError();

    DER_ConvertBitString(&i->subjectPublicKey);
    switch(SECOID_FindOIDTag(&i->algorithm.algorithm)) {
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
            rv = SEC_ASN1DecodeItem(arena, pk, SECKEY_RSAPublicKeyTemplate,
                                    &i->subjectPublicKey);
            if (rv) return rv;
            sprintf(mm, "%s.rsaPublicKey.", msg);
            sv_PrintRSAPublicKey(out, pk, mm);
            break;
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
            rv = SEC_ASN1DecodeItem(arena, pk, SECKEY_DSAPublicKeyTemplate,
                                    &i->subjectPublicKey);
            if (rv) return rv;
            sprintf(mm, "%s.dsaPublicKey.", msg);
            sv_PrintDSAPublicKey(out, pk, mm);
            break;
        default:
            fprintf(out, "%s=bad SPKI algorithm type\n", msg);
            return 0;
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sv_PrintTime ( FILE out,
SECItem *  t,
char *  m 
)

Definition at line 109 of file pk7print.c.

{
    PRExplodedTime printableTime; 
    int64 time;
    char *timeString;
    int rv;

    rv = DER_DecodeTimeChoice(&time, t);
    if (rv) return rv;

    /* Convert to local time */
    PR_ExplodeTime(time, PR_LocalTimeParameters, &printableTime);

    timeString = (char *)PORT_Alloc(100);

    if ( timeString ) {
        PR_FormatTime( timeString, 100, "%a %b %d %H:%M:%S %Y", &printableTime );
        fprintf(out, "%s%s\n", m, timeString);
        PORT_Free(timeString);
        return 0;
    }
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sv_PrintValidity ( FILE out,
CERTValidity *  v,
char *  m 
)

Definition at line 134 of file pk7print.c.

{
    int rv;

    fprintf(out, m);
    rv = sv_PrintTime(out, &v->notBefore, "notBefore=");
    if (rv) return rv;
    fprintf(out, m);
    sv_PrintTime(out, &v->notAfter, "notAfter=");
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function: