Compare commits
1 Commits
tags/Makef
...
tags/STABL
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e47a46b213 |
@@ -1,539 +0,0 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial
|
||||
* field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
/*
|
||||
* GF2m_ecl.c: Contains an implementation of elliptic curve math library
|
||||
* for curves over GF2m.
|
||||
*
|
||||
* XXX Can be moved to a separate subdirectory later.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GF2m_ecl.h"
|
||||
#include "mpi/mplogic.h"
|
||||
#include "mpi/mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
GF2m_ec_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
GF2m_ec_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.2.
|
||||
* Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_add_aff(const mp_int *pp, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int lambda, xtemp, ytemp;
|
||||
unsigned int *p;
|
||||
int p_size;
|
||||
|
||||
p_size = mp_bpoly2arr(pp, p, 0) + 1;
|
||||
p = (unsigned int *) (malloc(sizeof(unsigned int) * p_size));
|
||||
if (p == NULL) goto cleanup;
|
||||
mp_bpoly2arr(pp, p, p_size);
|
||||
|
||||
CHECK_MPI_OK( mp_init(&lambda) );
|
||||
CHECK_MPI_OK( mp_init(&xtemp) );
|
||||
CHECK_MPI_OK( mp_init(&ytemp) );
|
||||
/* if P = inf, then R = Q */
|
||||
if (GF2m_ec_pt_is_inf_aff(px, py) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(qx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(qy, ry) );
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (GF2m_ec_pt_is_inf_aff(qx, qy) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(px, rx) );
|
||||
CHECK_MPI_OK( mp_copy(py, ry) );
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* if px != qx, then lambda = (py+qy) / (px+qx),
|
||||
* xtemp = a + lambda^2 + lambda + px + qx
|
||||
*/
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
CHECK_MPI_OK( mp_badd(py, qy, &ytemp) );
|
||||
CHECK_MPI_OK( mp_badd(px, qx, &xtemp) );
|
||||
CHECK_MPI_OK( mp_bdivmod(&ytemp, &xtemp, pp, p, &lambda) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(&lambda, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, &lambda, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, a, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, px, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, qx, &xtemp) );
|
||||
} else {
|
||||
/* if py != qy or qx = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qx) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* lambda = qx + qy / qx */
|
||||
CHECK_MPI_OK( mp_bdivmod(qy, qx, pp, p, &lambda) );
|
||||
CHECK_MPI_OK( mp_badd(&lambda, qx, &lambda) );
|
||||
/* xtemp = a + lambda^2 + lambda */
|
||||
CHECK_MPI_OK( mp_bsqrmod(&lambda, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, &lambda, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, a, &xtemp) );
|
||||
}
|
||||
/* ry = (qx + xtemp) * lambda + xtemp + qy */
|
||||
CHECK_MPI_OK( mp_badd(qx, &xtemp, &ytemp) );
|
||||
CHECK_MPI_OK( mp_bmulmod(&ytemp, &lambda, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_badd(&ytemp, &xtemp, &ytemp) );
|
||||
CHECK_MPI_OK( mp_badd(&ytemp, qy, ry) );
|
||||
/* rx = xtemp */
|
||||
CHECK_MPI_OK( mp_copy(&xtemp, rx) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&xtemp);
|
||||
mp_clear(&ytemp);
|
||||
free(p);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q.
|
||||
* Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_sub_aff(const mp_int *pp, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int nqy;
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
CHECK_MPI_OK( mp_init(&nqy) );
|
||||
/* nqy = qx+qy */
|
||||
CHECK_MPI_OK( mp_badd(qx, qy, &nqy) );
|
||||
err = GF2m_ec_pt_add_aff(pp, a, px, py, qx, &nqy, rx, ry);
|
||||
cleanup:
|
||||
mp_clear(&nqy);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = 2P.
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_dbl_aff(const mp_int *pp, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
return GF2m_ec_pt_add_aff(pp, a, px, py, px, py, rx, ry);
|
||||
}
|
||||
|
||||
/* Gets the i'th bit in the binary representation of a.
|
||||
* If i >= length(a), then return 0.
|
||||
* (The above behaviour differs from mpl_get_bit, which
|
||||
* causes an error if i >= length(a).)
|
||||
*/
|
||||
#define MP_GET_BIT(a, i) \
|
||||
((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i))
|
||||
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3.
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_mul_aff(const mp_int *pp, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
unsigned int *p;
|
||||
int p_size;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&k3) );
|
||||
CHECK_MPI_OK( mp_init(&qx) );
|
||||
CHECK_MPI_OK( mp_init(&qy) );
|
||||
CHECK_MPI_OK( mp_init(&sx) );
|
||||
CHECK_MPI_OK( mp_init(&sy) );
|
||||
|
||||
p_size = mp_bpoly2arr(pp, p, 0) + 1;
|
||||
p = (unsigned int *) (malloc(sizeof(unsigned int) * p_size));
|
||||
if (p == NULL) goto cleanup;
|
||||
mp_bpoly2arr(pp, p, p_size);
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
CHECK_MPI_OK( mp_copy(px, &qx) );
|
||||
CHECK_MPI_OK( mp_copy(py, &qy) );
|
||||
CHECK_MPI_OK( mp_copy(n, &k) );
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
CHECK_MPI_OK( mp_badd(&qx, &qy, &qy) );
|
||||
CHECK_MPI_OK( mp_neg(&k, &k) );
|
||||
}
|
||||
#ifdef EC_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
mp_zero(&sx);
|
||||
mp_zero(&sy);
|
||||
for (i = l; i >= 0; i--) {
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_add_aff(pp, a, &sx, &sy, &qx, &qy, &sx, &sy) );
|
||||
}
|
||||
if (i > 0) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GF2m_ec_pt_dbl_aff(pp, a, &sx, &sy, &sx, &sy) );
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from standard */
|
||||
/* k3 = 3 * k */
|
||||
mp_set(&k3, 0x3);
|
||||
CHECK_MPI_OK( mp_mul(&k, &k3, &k3) );
|
||||
/* S = Q */
|
||||
CHECK_MPI_OK( mp_copy(&qx, &sx) );
|
||||
CHECK_MPI_OK( mp_copy(&qy, &sy) );
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GF2m_ec_pt_dbl_aff(pp, a, &sx, &sy, &sx, &sy) );
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_add_aff(pp, a, &sx, &sy, &qx, &qy, &sx, &sy) );
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_sub_aff(pp, a, &sx, &sy, &qx, &qy, &sx, &sy) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
CHECK_MPI_OK( mp_copy(&sx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(&sy, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
free(p);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
|
||||
* coordinates.
|
||||
* Uses algorithm Mdouble in appendix of
|
||||
* Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation".
|
||||
* modified to not require precomputation of c=b^{2^{m-1}}.
|
||||
*/
|
||||
static mp_err
|
||||
gf2m_Mdouble(const mp_int *pp, const unsigned int p[], const mp_int *a,
|
||||
const mp_int *b, mp_int *x, mp_int *z)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int t1;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
CHECK_MPI_OK( mp_init(&t1) );
|
||||
|
||||
CHECK_MPI_OK( mp_bsqrmod(x, p, x) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(z, p, &t1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(x, &t1, p, z) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(x, p, x) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(&t1, p, &t1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(b, &t1, p, &t1) );
|
||||
CHECK_MPI_OK( mp_badd(x, &t1, x) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&t1);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery
|
||||
* projective coordinates.
|
||||
* Uses algorithm Madd in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation".
|
||||
*/
|
||||
static mp_err
|
||||
gf2m_Madd(const mp_int *pp, const unsigned int p[], const mp_int *a,
|
||||
const mp_int *b, const mp_int *x, mp_int *x1, mp_int *z1, mp_int *x2,
|
||||
mp_int *z2)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int t1, t2;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&t2) = 0;
|
||||
CHECK_MPI_OK( mp_init(&t1) );
|
||||
CHECK_MPI_OK( mp_init(&t2) );
|
||||
|
||||
CHECK_MPI_OK( mp_copy(x, &t1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(x1, z2, p, x1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(z1, x2, p, z1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(x1, z1, p, &t2) );
|
||||
CHECK_MPI_OK( mp_badd(z1, x1, z1) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(z1, p, z1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(z1, &t1, p, x1) );
|
||||
CHECK_MPI_OK( mp_badd(x1, &t2, x1) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&t1);
|
||||
mp_clear(&t2);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
|
||||
* using Montgomery point multiplication algorithm Mxy() in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation".
|
||||
* Returns:
|
||||
* 0 on error
|
||||
* 1 if return value should be the point at infinity
|
||||
* 2 otherwise
|
||||
*/
|
||||
static int
|
||||
gf2m_Mxy(const mp_int *pp, const unsigned int p[], const mp_int *a,
|
||||
const mp_int *b, const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1,
|
||||
mp_int *x2, mp_int *z2)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
int ret;
|
||||
mp_int t3, t4, t5;
|
||||
|
||||
MP_DIGITS(&t3) = 0;
|
||||
MP_DIGITS(&t4) = 0;
|
||||
MP_DIGITS(&t5) = 0;
|
||||
CHECK_MPI_OK( mp_init(&t3) );
|
||||
CHECK_MPI_OK( mp_init(&t4) );
|
||||
CHECK_MPI_OK( mp_init(&t5) );
|
||||
|
||||
if (mp_cmp_z(z1) == 0) {
|
||||
mp_zero(x2);
|
||||
mp_zero(z2);
|
||||
ret = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (mp_cmp_z(z2) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(x, x2) );
|
||||
CHECK_MPI_OK( mp_badd(x, y, z2) );
|
||||
ret = 2;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
mp_set(&t5, 0x1);
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(z1, z2, p, &t3) );
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(z1, x, p, z1) );
|
||||
CHECK_MPI_OK( mp_badd(z1, x1, z1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(z2, x, p, z2) );
|
||||
CHECK_MPI_OK( mp_bmulmod(z2, x1, p, x1) );
|
||||
CHECK_MPI_OK( mp_badd(z2, x2, z2) );
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(z2, z1, p, z2) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(x, p, &t4) );
|
||||
CHECK_MPI_OK( mp_badd(&t4, y, &t4) );
|
||||
CHECK_MPI_OK( mp_bmulmod(&t4, &t3, p, &t4) );
|
||||
CHECK_MPI_OK( mp_badd(&t4, z2, &t4) );
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(&t3, x, p, &t3) );
|
||||
CHECK_MPI_OK( mp_bdivmod(&t5, &t3, pp, p, &t3) );
|
||||
CHECK_MPI_OK( mp_bmulmod(&t3, &t4, p, &t4) );
|
||||
CHECK_MPI_OK( mp_bmulmod(x1, &t3, p, x2) );
|
||||
CHECK_MPI_OK( mp_badd(x2, x, z2) );
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(z2, &t4, p, z2) );
|
||||
CHECK_MPI_OK( mp_badd(z2, y, z2) );
|
||||
|
||||
ret = 2;
|
||||
|
||||
cleanup:
|
||||
mp_clear(&t3);
|
||||
mp_clear(&t4);
|
||||
mp_clear(&t5);
|
||||
if (err == MP_OKAY) {
|
||||
return ret;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes R = nP based on algorithm 2P of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation".
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses Montgomery projective coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_mul_mont(const mp_int *pp, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int x1, x2, z1, z2;
|
||||
int i, j;
|
||||
mp_digit top_bit, mask;
|
||||
unsigned int *p;
|
||||
int p_size;
|
||||
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&x2) = 0;
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
CHECK_MPI_OK( mp_init(&x1) );
|
||||
CHECK_MPI_OK( mp_init(&x2) );
|
||||
CHECK_MPI_OK( mp_init(&z1) );
|
||||
CHECK_MPI_OK( mp_init(&z2) );
|
||||
|
||||
p_size = mp_bpoly2arr(pp, p, 0) + 1;
|
||||
p = (unsigned int *) (malloc(sizeof(unsigned int) * p_size));
|
||||
if (p == NULL) goto cleanup;
|
||||
mp_bpoly2arr(pp, p, p_size);
|
||||
|
||||
/* if result should be point at infinity */
|
||||
if ((mp_cmp_z(n) == 0) || (GF2m_ec_pt_is_inf_aff(px, py) == MP_YES)) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_set_inf_aff(rx, ry) );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
CHECK_MPI_OK( mp_copy(rx, &x2) ); /* x2 = rx */
|
||||
CHECK_MPI_OK( mp_copy(ry, &z2) ); /* z2 = ry */
|
||||
|
||||
CHECK_MPI_OK( mp_copy(px, &x1) ); /* x1 = px */
|
||||
mp_set(&z1, 0x1); /* z1 = 1 */
|
||||
CHECK_MPI_OK( mp_bsqrmod(&x1, p, &z2) ); /* z2 = x1^2 = x2^2 */
|
||||
CHECK_MPI_OK( mp_bsqrmod(&z2, p, &x2) );
|
||||
CHECK_MPI_OK( mp_badd(&x2, b, &x2) ); /* x2 = px^4 + b */
|
||||
|
||||
/* find top-most bit and go one past it */
|
||||
i = MP_USED(n) - 1;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
top_bit = 1;
|
||||
top_bit <<= MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
while (!(MP_DIGITS(n)[i] & mask)) {
|
||||
mask >>= 1;
|
||||
j--;
|
||||
}
|
||||
mask >>= 1; j--;
|
||||
|
||||
/* if top most bit was at word break, go to next word */
|
||||
if (!mask) {
|
||||
i--;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
for (; i >= 0; i--) {
|
||||
for (; j >= 0; j--) {
|
||||
if (MP_DIGITS(n)[i] & mask) {
|
||||
CHECK_MPI_OK( gf2m_Madd(pp, p, a, b, px, &x1, &z1, &x2, &z2) );
|
||||
CHECK_MPI_OK( gf2m_Mdouble(pp, p, a, b, &x2, &z2) );
|
||||
} else {
|
||||
CHECK_MPI_OK( gf2m_Madd(pp, p, a, b, px, &x2, &z2, &x1, &z1) );
|
||||
CHECK_MPI_OK( gf2m_Mdouble(pp, p, a, b, &x1, &z1) );
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
/* convert out of "projective" coordinates */
|
||||
i = gf2m_Mxy(pp, p, a, b, px, py, &x1, &z1, &x2, &z2);
|
||||
if (i == 0) {
|
||||
err = MP_BADARG;
|
||||
goto cleanup;
|
||||
} else if (i == 1) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_set_inf_aff(rx, ry) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_copy(&x2, rx) );
|
||||
CHECK_MPI_OK( mp_copy(&z2, ry) );
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mp_clear(&x1);
|
||||
mp_clear(&x2);
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
free(p);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial
|
||||
* field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __gf2m_ecl_h_
|
||||
#define __gf2m_ecl_h_
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
#include "secmpi.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err GF2m_ec_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err GF2m_ec_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx, qy).
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err GF2m_ec_pt_add_aff(const mp_int *pp, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err GF2m_ec_pt_sub_aff(const mp_int *pp, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err GF2m_ec_pt_dbl_aff(const mp_int *pp, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses affine coordinates.
|
||||
*/
|
||||
mp_err GF2m_ec_pt_mul_aff(const mp_int *pp, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses Montgomery projective coordinates.
|
||||
*/
|
||||
mp_err GF2m_ec_pt_mul_mont(const mp_int *pp, const mp_int *a,
|
||||
const mp_int *b, const mp_int *px, const mp_int *py,
|
||||
const mp_int *n, mp_int *rx, mp_int *ry);
|
||||
|
||||
#define GF2m_ec_pt_is_inf(px, py) GF2m_ec_pt_is_inf_aff((px), (py))
|
||||
#define GF2m_ec_pt_add(p, a, px, py, qx, qy, rx, ry) \
|
||||
GF2m_ec_pt_add_aff((p), (a), (px), (py), (qx), (qy), (rx), (ry))
|
||||
|
||||
#define GF2m_ECL_MONTGOMERY
|
||||
#ifdef GF2m_ECL_AFFINE
|
||||
#define GF2m_ec_pt_mul(pp, a, b, px, py, n, rx, ry) \
|
||||
GF2m_ec_pt_mul_aff((pp), (a), (b), (px), (py), (n), (rx), (ry))
|
||||
#elif defined(GF2m_ECL_MONTGOMERY)
|
||||
#define GF2m_ec_pt_mul(pp, a, b, px, py, n, rx, ry) \
|
||||
GF2m_ec_pt_mul_mont((pp), (a), (b), (px), (py), (n), (rx), (ry))
|
||||
#endif /* GF2m_ECL_AFFINE or GF2m_ECL_MONTGOMERY */
|
||||
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
#endif /* __gf2m_ecl_h_ */
|
||||
@@ -1,647 +0,0 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime
|
||||
* field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
/*
|
||||
* GFp_ecl.c: Contains an implementation of elliptic curve math library
|
||||
* for curves over GFp.
|
||||
*
|
||||
* XXX Can be moved to a separate subdirectory later.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GFp_ecl.h"
|
||||
#include "mpi/mplogic.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
GFp_ec_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
GFp_ec_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.1.
|
||||
* Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_add_aff(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int lambda, temp, xtemp, ytemp;
|
||||
|
||||
CHECK_MPI_OK( mp_init(&lambda) );
|
||||
CHECK_MPI_OK( mp_init(&temp) );
|
||||
CHECK_MPI_OK( mp_init(&xtemp) );
|
||||
CHECK_MPI_OK( mp_init(&ytemp) );
|
||||
/* if P = inf, then R = Q */
|
||||
if (GFp_ec_pt_is_inf_aff(px, py) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(qx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(qy, ry) );
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (GFp_ec_pt_is_inf_aff(qx, qy) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(px, rx) );
|
||||
CHECK_MPI_OK( mp_copy(py, ry) );
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* if px != qx, then lambda = (py-qy) / (px-qx) */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
CHECK_MPI_OK( mp_submod(py, qy, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_submod(px, qx, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_invmod(&xtemp, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_mulmod(&ytemp, &xtemp, p, &lambda) );
|
||||
} else {
|
||||
/* if py != qy or qy = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* lambda = (3qx^2+a) / (2qy) */
|
||||
CHECK_MPI_OK( mp_sqrmod(qx, p, &xtemp) );
|
||||
mp_set(&temp, 0x3);
|
||||
CHECK_MPI_OK( mp_mulmod(&xtemp, &temp, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_addmod(&xtemp, a, p, &xtemp) );
|
||||
mp_set(&temp, 0x2);
|
||||
CHECK_MPI_OK( mp_mulmod(qy, &temp, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_invmod(&ytemp, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_mulmod(&xtemp, &ytemp, p, &lambda) );
|
||||
}
|
||||
/* rx = lambda^2 - px - qx */
|
||||
CHECK_MPI_OK( mp_sqrmod(&lambda, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_submod(&xtemp, px, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_submod(&xtemp, qx, p, &xtemp) );
|
||||
/* ry = (x1-x2) * lambda - y1 */
|
||||
CHECK_MPI_OK( mp_submod(qx, &xtemp, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_mulmod(&ytemp, &lambda, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_submod(&ytemp, qy, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_copy(&xtemp, rx) );
|
||||
CHECK_MPI_OK( mp_copy(&ytemp, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&temp);
|
||||
mp_clear(&xtemp);
|
||||
mp_clear(&ytemp);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q.
|
||||
* Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_sub_aff(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int nqy;
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
CHECK_MPI_OK( mp_init(&nqy) );
|
||||
/* nqy = -qy */
|
||||
CHECK_MPI_OK( mp_neg(qy, &nqy) );
|
||||
err = GFp_ec_pt_add_aff(p, a, px, py, qx, &nqy, rx, ry);
|
||||
cleanup:
|
||||
mp_clear(&nqy);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = 2P.
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_dbl_aff(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
return GFp_ec_pt_add_aff(p, a, px, py, px, py, rx, ry);
|
||||
}
|
||||
|
||||
/* Gets the i'th bit in the binary representation of a.
|
||||
* If i >= length(a), then return 0.
|
||||
* (The above behaviour differs from mpl_get_bit, which
|
||||
* causes an error if i >= length(a).)
|
||||
*/
|
||||
#define MP_GET_BIT(a, i) \
|
||||
((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i))
|
||||
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3.
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_mul_aff(const mp_int *p, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n, mp_int *rx,
|
||||
mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&k3) );
|
||||
CHECK_MPI_OK( mp_init(&qx) );
|
||||
CHECK_MPI_OK( mp_init(&qy) );
|
||||
CHECK_MPI_OK( mp_init(&sx) );
|
||||
CHECK_MPI_OK( mp_init(&sy) );
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
CHECK_MPI_OK( mp_copy(px, &qx) );
|
||||
CHECK_MPI_OK( mp_copy(py, &qy) );
|
||||
CHECK_MPI_OK( mp_copy(n, &k) );
|
||||
/* if n < 0 Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
CHECK_MPI_OK( mp_neg(&qy, &qy) );
|
||||
CHECK_MPI_OK( mp_mod(&qy, p, &qy) );
|
||||
CHECK_MPI_OK( mp_neg(&k, &k) );
|
||||
CHECK_MPI_OK( mp_mod(&k, p, &k) );
|
||||
}
|
||||
#ifdef EC_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
mp_zero(&sx);
|
||||
mp_zero(&sy);
|
||||
for (i = l; i >= 0; i--) {
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_add_aff(p, a, &sx, &sy,
|
||||
&qx, &qy, &sx, &sy) );
|
||||
}
|
||||
if (i > 0) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GFp_ec_pt_dbl_aff(p, a, &sx, &sy, &sx, &sy) );
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from standard */
|
||||
/* k3 = 3 * k */
|
||||
mp_set(&k3, 0x3);
|
||||
CHECK_MPI_OK( mp_mul(&k, &k3, &k3) );
|
||||
/* S = Q */
|
||||
CHECK_MPI_OK( mp_copy(&qx, &sx) );
|
||||
CHECK_MPI_OK( mp_copy(&qy, &sy) );
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GFp_ec_pt_dbl_aff(p, a, &sx, &sy, &sx, &sy) );
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_add_aff(p, a, &sx, &sy,
|
||||
&qx, &qy, &sx, &sy) );
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_sub_aff(p, a, &sx, &sy,
|
||||
&qx, &qy, &sx, &sy) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
CHECK_MPI_OK( mp_copy(&sx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(&sy, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). P and R can share x and y coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *p, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int z1, z2, z3;
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_DIGITS(&z3) = 0;
|
||||
CHECK_MPI_OK( mp_init(&z1) );
|
||||
CHECK_MPI_OK( mp_init(&z2) );
|
||||
CHECK_MPI_OK( mp_init(&z3) );
|
||||
|
||||
/* if point at infinity, then set point at infinity and exit */
|
||||
if (GFp_ec_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_set_inf_aff(rx, ry) );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* transform (px, py, pz) into (px / pz^2, py / pz^3) */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(px, rx) );
|
||||
CHECK_MPI_OK( mp_copy(py, ry) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_invmod(pz, p, &z1) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&z1, p, &z2) );
|
||||
CHECK_MPI_OK( mp_mulmod(&z1, &z2, p, &z3) );
|
||||
CHECK_MPI_OK( mp_mulmod(px, &z2, p, rx) );
|
||||
CHECK_MPI_OK( mp_mulmod(py, &z3, p, ry) );
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
mp_clear(&z3);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity.
|
||||
* Uses Jacobian coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_is_inf_jac(const mp_int *px, const mp_int *py, const mp_int *pz)
|
||||
{
|
||||
return mp_cmp_z(pz);
|
||||
}
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz)
|
||||
{
|
||||
mp_zero(pz);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and
|
||||
* Q is (qx, qy, qz). Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses Jacobian coordinates.
|
||||
*
|
||||
* This routine implements Point Addition in the Jacobian Projective
|
||||
* space as described in the paper "Efficient elliptic curve exponentiation
|
||||
* using mixed coordinates", by H. Cohen, A Miyaji, T. Ono.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_add_jac(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, const mp_int *qz, mp_int *rx, mp_int *ry, mp_int *rz)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int n0, u1, u2, s1, s2, H, G;
|
||||
MP_DIGITS(&n0) = 0;
|
||||
MP_DIGITS(&u1) = 0;
|
||||
MP_DIGITS(&u2) = 0;
|
||||
MP_DIGITS(&s1) = 0;
|
||||
MP_DIGITS(&s2) = 0;
|
||||
MP_DIGITS(&H) = 0;
|
||||
MP_DIGITS(&G) = 0;
|
||||
CHECK_MPI_OK( mp_init(&n0) );
|
||||
CHECK_MPI_OK( mp_init(&u1) );
|
||||
CHECK_MPI_OK( mp_init(&u2) );
|
||||
CHECK_MPI_OK( mp_init(&s1) );
|
||||
CHECK_MPI_OK( mp_init(&s2) );
|
||||
CHECK_MPI_OK( mp_init(&H) );
|
||||
CHECK_MPI_OK( mp_init(&G) );
|
||||
|
||||
/* Use point double if pointers are equal. */
|
||||
if ((px == qx) && (py == qy) && (pz == qz)) {
|
||||
err = GFp_ec_pt_dbl_jac(p, a, px, py, pz, rx, ry, rz);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* If either P or Q is the point at infinity, then return
|
||||
* the other point
|
||||
*/
|
||||
if (GFp_ec_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
CHECK_MPI_OK( mp_copy(qx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(qy, ry) );
|
||||
CHECK_MPI_OK( mp_copy(qz, rz) );
|
||||
goto cleanup;
|
||||
}
|
||||
if (GFp_ec_pt_is_inf_jac(qx, qy, qz) == MP_YES) {
|
||||
CHECK_MPI_OK( mp_copy(px, rx) );
|
||||
CHECK_MPI_OK( mp_copy(py, ry) );
|
||||
CHECK_MPI_OK( mp_copy(pz, rz) );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Compute u1 = px * qz^2, s1 = py * qz^3 */
|
||||
if (mp_cmp_d(qz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(px, &u1) );
|
||||
CHECK_MPI_OK( mp_copy(py, &s1) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_sqrmod(qz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(px, &n0, p, &u1) );
|
||||
CHECK_MPI_OK( mp_mulmod(&n0, qz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(py, &n0, p, &s1) );
|
||||
}
|
||||
|
||||
/* Compute u2 = qx * pz^2, s2 = qy * pz^3 */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(qx, &u2) );
|
||||
CHECK_MPI_OK( mp_copy(qy, &s2) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_sqrmod(pz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(qx, &n0, p, &u2) );
|
||||
CHECK_MPI_OK( mp_mulmod(&n0, pz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(qy, &n0, p, &s2) );
|
||||
}
|
||||
|
||||
/* Compute H = u2 - u1 ; G = s2 - s1 */
|
||||
CHECK_MPI_OK( mp_submod(&u2, &u1, p, &H) );
|
||||
CHECK_MPI_OK( mp_submod(&s2, &s1, p, &G) );
|
||||
|
||||
if (mp_cmp_z(&H) == 0) {
|
||||
if (mp_cmp_z(&G) == 0) {
|
||||
/* P = Q; double */
|
||||
err = GFp_ec_pt_dbl_jac(p, a, px, py, pz,
|
||||
rx, ry, rz);
|
||||
goto cleanup;
|
||||
} else {
|
||||
/* P = -Q; return point at infinity */
|
||||
CHECK_MPI_OK( GFp_ec_pt_set_inf_jac(rx, ry, rz) );
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
if (mp_cmp_d(qz, 1) == 0) {
|
||||
/* if pz == qz == 1, then rz = H */
|
||||
CHECK_MPI_OK( mp_copy(&H, rz) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_mulmod(qz, &H, p, rz) );
|
||||
}
|
||||
} else {
|
||||
if (mp_cmp_d(qz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_mulmod(pz, &H, p, rz) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_mulmod(pz, qz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(&n0, &H, p, rz) );
|
||||
}
|
||||
}
|
||||
|
||||
/* rx = G^2 - H^3 - 2 * u1 * H^2 */
|
||||
CHECK_MPI_OK( mp_sqrmod(&G, p, rx) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&H, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(&n0, &u1, p, &u1) );
|
||||
CHECK_MPI_OK( mp_addmod(&u1, &u1, p, &u2) );
|
||||
CHECK_MPI_OK( mp_mulmod(&H, &n0, p, &H) );
|
||||
CHECK_MPI_OK( mp_submod(rx, &H, p, rx) );
|
||||
CHECK_MPI_OK( mp_submod(rx, &u2, p, rx) );
|
||||
|
||||
/* ry = - s1 * H^3 + G * (u1 * H^2 - rx) */
|
||||
/* (formula based on values of variables before block above) */
|
||||
CHECK_MPI_OK( mp_submod(&u1, rx, p, &u1) );
|
||||
CHECK_MPI_OK( mp_mulmod(&G, &u1, p, ry) );
|
||||
CHECK_MPI_OK( mp_mulmod(&s1, &H, p, &s1) );
|
||||
CHECK_MPI_OK( mp_submod(ry, &s1, p, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&n0);
|
||||
mp_clear(&u1);
|
||||
mp_clear(&u2);
|
||||
mp_clear(&s1);
|
||||
mp_clear(&s2);
|
||||
mp_clear(&H);
|
||||
mp_clear(&G);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Jacobian coordinates.
|
||||
*
|
||||
* This routine implements Point Doubling in the Jacobian Projective
|
||||
* space as described in the paper "Efficient elliptic curve exponentiation
|
||||
* using mixed coordinates", by H. Cohen, A Miyaji, T. Ono.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_dbl_jac(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *pz, mp_int *rx, mp_int *ry, mp_int *rz)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int t0, t1, M, S;
|
||||
MP_DIGITS(&t0) = 0;
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&M) = 0;
|
||||
MP_DIGITS(&S) = 0;
|
||||
CHECK_MPI_OK( mp_init(&t0) );
|
||||
CHECK_MPI_OK( mp_init(&t1) );
|
||||
CHECK_MPI_OK( mp_init(&M) );
|
||||
CHECK_MPI_OK( mp_init(&S) );
|
||||
|
||||
if (GFp_ec_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_set_inf_jac(rx, ry, rz) );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
/* M = 3 * px^2 + a */
|
||||
CHECK_MPI_OK( mp_sqrmod(px, p, &t0) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &t0, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &M, p, &t0) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, a, p, &M) );
|
||||
} else if (mp_cmp_int(a, -3) == 0) {
|
||||
/* M = 3 * (px + pz^2) * (px - pz) */
|
||||
CHECK_MPI_OK( mp_sqrmod(pz, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(px, &M, p, &t0) );
|
||||
CHECK_MPI_OK( mp_submod(px, &M, p, &t1) );
|
||||
CHECK_MPI_OK( mp_mulmod(&t0, &t1, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(&M, &M, p, &t0) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &M, p, &M) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_sqrmod(px, p, &t0) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &t0, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &M, p, &t0) );
|
||||
CHECK_MPI_OK( mp_sqrmod(pz, p, &M) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&M, p, &M) );
|
||||
CHECK_MPI_OK( mp_mulmod(&M, a, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(&M, &t0, p, &M) );
|
||||
}
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_addmod(py, py, p, rz) );
|
||||
CHECK_MPI_OK( mp_sqrmod(rz, p, &t0) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_addmod(py, py, p, &t0) );
|
||||
CHECK_MPI_OK( mp_mulmod(&t0, pz, p, rz) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&t0, p, &t0) );
|
||||
}
|
||||
|
||||
/* S = 4 * px * py^2 = pz * (2 * py)^2 */
|
||||
CHECK_MPI_OK( mp_mulmod(px, &t0, p, &S) );
|
||||
|
||||
/* rx = M^2 - 2 * S */
|
||||
CHECK_MPI_OK( mp_addmod(&S, &S, p, &t1) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&M, p, rx) );
|
||||
CHECK_MPI_OK( mp_submod(rx, &t1, p, rx) );
|
||||
|
||||
/* ry = M * (S - rx) - 8 * py^4 */
|
||||
CHECK_MPI_OK( mp_sqrmod(&t0, p, &t1) );
|
||||
if (mp_isodd(&t1)) {
|
||||
CHECK_MPI_OK( mp_add(&t1, p, &t1) );
|
||||
}
|
||||
CHECK_MPI_OK( mp_div_2(&t1, &t1) );
|
||||
CHECK_MPI_OK( mp_submod(&S, rx, p, &S) );
|
||||
CHECK_MPI_OK( mp_mulmod(&M, &S, p, &M) );
|
||||
CHECK_MPI_OK( mp_submod(&M, &t1, p, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&t0);
|
||||
mp_clear(&t1);
|
||||
mp_clear(&M);
|
||||
mp_clear(&S);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses Jacobian coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_mul_jac(const mp_int *p, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int k, qx, qy, qz, sx, sy, sz;
|
||||
int i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&qz) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_DIGITS(&sz) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&qx) );
|
||||
CHECK_MPI_OK( mp_init(&qy) );
|
||||
CHECK_MPI_OK( mp_init(&qz) );
|
||||
CHECK_MPI_OK( mp_init(&sx) );
|
||||
CHECK_MPI_OK( mp_init(&sy) );
|
||||
CHECK_MPI_OK( mp_init(&sz) );
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
/* if n < 0 then out of range error */
|
||||
} else if (mp_cmp_z(n) < 0) {
|
||||
err = MP_RANGE;
|
||||
goto cleanup;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
CHECK_MPI_OK( mp_copy(px, &qx) );
|
||||
CHECK_MPI_OK( mp_copy(py, &qy) );
|
||||
CHECK_MPI_OK( mp_set_int(&qz, 1) );
|
||||
CHECK_MPI_OK( mp_copy(n, &k) );
|
||||
|
||||
/* double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
mp_zero(&sx);
|
||||
mp_zero(&sy);
|
||||
mp_zero(&sz);
|
||||
for (i = l; i >= 0; i--) {
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (MP_GET_BIT(&k, i) != 0) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_add_jac(p, a, &sx, &sy, &sz,
|
||||
&qx, &qy, &qz, &sx, &sy, &sz) );
|
||||
}
|
||||
if (i > 0) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GFp_ec_pt_dbl_jac(p, a, &sx, &sy, &sz,
|
||||
&sx, &sy, &sz) );
|
||||
}
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
CHECK_MPI_OK( GFp_ec_pt_jac2aff(&sx, &sy, &sz, p, rx, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&qz);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
mp_clear(&sz);
|
||||
return err;
|
||||
}
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime
|
||||
* field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __gfp_ecl_h_
|
||||
#define __gfp_ecl_h_
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
#include "secmpi.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
extern mp_err GFp_ec_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
extern mp_err GFp_ec_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx, qy).
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_add_aff(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
extern mp_err GFp_ec_pt_sub_aff(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
extern mp_err GFp_ec_pt_dbl_aff(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses affine coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_mul_aff(const mp_int *p, const mp_int *a,
|
||||
const mp_int *b, const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry).
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_jac2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *p, mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_is_inf_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and
|
||||
* Q is (qx, qy, qz). Uses Jacobian coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_add_jac(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *qx, const mp_int *qy, const mp_int *qz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz);
|
||||
|
||||
/* Computes R = 2P. Uses Jacobian coordinates. */
|
||||
extern mp_err GFp_ec_pt_dbl_jac(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses Jacobian coordinates.
|
||||
*/
|
||||
mp_err GFp_ec_pt_mul_jac(const mp_int *p, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
#define GFp_ec_pt_is_inf(px, py) GFp_ec_pt_is_inf_aff((px), (py))
|
||||
#define GFp_ec_pt_add(p, a, px, py, qx, qy, rx, ry) \
|
||||
GFp_ec_pt_add_aff((p), (a), (px), (py), (qx), (qy), (rx), (ry))
|
||||
|
||||
#define GFp_ECL_JACOBIAN
|
||||
#ifdef GFp_ECL_AFFINE
|
||||
#define GFp_ec_pt_mul(p, a, b, px, py, n, rx, ry) \
|
||||
GFp_ec_pt_mul_aff((p), (a), (b), (px), (py), (n), (rx), (ry))
|
||||
#elif defined(GFp_ECL_JACOBIAN)
|
||||
#define GFp_ec_pt_mul(p, a, b, px, py, n, rx, ry) \
|
||||
GFp_ec_pt_mul_jac((p), (a), (b), (px), (py), (n), (rx), (ry))
|
||||
#endif /* GFp_ECL_AFFINE or GFp_ECL_JACOBIAN*/
|
||||
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
#endif /* __gfp_ecl_h_ */
|
||||
@@ -1,339 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
-include config.mk
|
||||
|
||||
ifdef USE_64
|
||||
DEFINES += -DNSS_USE_64
|
||||
endif
|
||||
|
||||
ifdef USE_HYBRID
|
||||
DEFINES += -DNSS_USE_HYBRID
|
||||
endif
|
||||
|
||||
# des.c wants _X86_ defined for intel CPUs.
|
||||
# coreconf does this for windows, but not for Linux, FreeBSD, etc.
|
||||
ifeq ($(CPU_ARCH),x86)
|
||||
ifneq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
OS_REL_CFLAGS += -D_X86_
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),OSF1)
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_NO_MP_WORD
|
||||
MPI_SRCS += mpvalpha.c
|
||||
endif
|
||||
|
||||
ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET))) #omits WIN16 and WINCE
|
||||
ifdef NS_USE_GCC
|
||||
# Ideally, we want to use assembler
|
||||
# ASFILES = mpi_x86.s
|
||||
# DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE \
|
||||
# -DMP_ASSEMBLY_DIV_2DX1D
|
||||
# but we haven't figured out how to make it work, so we are not
|
||||
# using assembler right now.
|
||||
ASFILES =
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT
|
||||
else
|
||||
ASFILES = mpi_x86.asm
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
endif
|
||||
ifdef BUILD_OPT
|
||||
ifndef NS_USE_GCC
|
||||
OPTIMIZER += -Ox # maximum optimization for freebl
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),WINCE)
|
||||
DEFINES += -DMP_ARGCHK=0 # no assert in WinCE
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
endif
|
||||
|
||||
ifdef XP_OS2_VACPP
|
||||
ASFILES = mpi_x86.asm
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),IRIX)
|
||||
ifeq ($(USE_N32),1)
|
||||
ASFILES = mpi_mips.s
|
||||
ifeq ($(NS_USE_GCC),1)
|
||||
ASFLAGS = -Wp,-P -Wp,-traditional -O -mips3
|
||||
else
|
||||
ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3
|
||||
endif
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
else
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),Linux)
|
||||
ifeq ($(CPU_ARCH),x86)
|
||||
ASFILES = mpi_x86.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),AIX)
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
ifndef USE_64
|
||||
DEFINES += -DMP_NO_DIV_WORD -DMP_NO_ADD_WORD -DMP_NO_SUB_WORD
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET), HP-UX)
|
||||
ifneq ($(OS_TEST), ia64)
|
||||
MKSHLIB += +k +vshlibunsats -u FREEBL_GetVector +e FREEBL_GetVector
|
||||
ifndef FREEBL_EXTENDED_BUILD
|
||||
ifdef USE_PURE_32
|
||||
# build for DA1.1 (HP PA 1.1) pure 32 bit model
|
||||
DEFINES += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
else
|
||||
ifdef USE_64
|
||||
# this builds for DA2.0W (HP PA 2.0 Wide), the LP64 ABI, using 32-bit digits
|
||||
MPI_SRCS += mpi_hp.c
|
||||
ASFILES += hpma512.s hppa20.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
else
|
||||
# this builds for DA2.0 (HP PA 2.0 Narrow) hybrid model
|
||||
# (the 32-bit ABI with 64-bit registers) using 32-bit digits
|
||||
MPI_SRCS += mpi_hp.c
|
||||
ASFILES += hpma512.s hppa20.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
# This is done in coreconf by defining USE_LONG_LONGS
|
||||
# OS_CFLAGS += -Aa +e +DA2.0 +DS2.0
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Note: -xarch=v8 or v9 is now done in coreconf
|
||||
ifeq ($(OS_TARGET),SunOS)
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
ifndef NS_USE_GCC
|
||||
ifdef USE_HYBRID
|
||||
OS_CFLAGS += -xchip=ultra2
|
||||
endif
|
||||
endif
|
||||
ifeq (5.5.1,$(firstword $(sort 5.5.1 $(OS_RELEASE))))
|
||||
SYSV_SPARC = 1
|
||||
endif
|
||||
ifeq ($(SYSV_SPARC),1)
|
||||
SOLARIS_AS = /usr/ccs/bin/as
|
||||
ifdef NS_USE_GCC
|
||||
ifdef GCC_USE_GNU_LD
|
||||
MKSHLIB += -Wl,-Bsymbolic,-z,defs,-z,now,-z,text,--version-script,mapfile.Solaris
|
||||
else
|
||||
MKSHLIB += -Wl,-B,symbolic,-z,defs,-z,now,-z,text,-M,mapfile.Solaris
|
||||
endif
|
||||
else
|
||||
MKSHLIB += -B symbolic -z defs -z now -z text -M mapfile.Solaris
|
||||
endif
|
||||
ifdef USE_PURE_32
|
||||
# this builds for Sparc v8 pure 32-bit architecture
|
||||
DEFINES += -DMP_USE_LONG_LONG_MULTIPLY -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
else
|
||||
ifdef USE_64
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
MPI_SRCS += mpi_sparc.c
|
||||
ASFILES = mpv_sparcv9.s montmulfv9.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_USING_MONT_MULF
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
# MPI_SRCS += mpv_sparc.c
|
||||
# removed -xdepend from the following line
|
||||
SOLARIS_FLAGS = -fast -xO5 -xrestrict=%all -xchip=ultra -xarch=v9a -KPIC -mt
|
||||
SOLARIS_AS_FLAGS = -xarch=v9a -K PIC
|
||||
else
|
||||
# this builds for Sparc v8+a hybrid architecture, 64-bit registers, 32-bit ABI
|
||||
MPI_SRCS += mpi_sparc.c
|
||||
ASFILES = mpv_sparcv8.s montmulfv8.s
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_ASSEMBLY_MULTIPLY -DMP_USING_MONT_MULF
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plusa -K PIC
|
||||
# ASM_SUFFIX = .S
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
else
|
||||
# Solaris x86
|
||||
DEFINES += -D_X86_
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
ASFILES = mpi_i86pc.s
|
||||
ifdef NS_USE_GCC
|
||||
LD = gcc
|
||||
AS = gcc
|
||||
ASFLAGS =
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c mac_rand.c os2_rand.c
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
export:: private_export
|
||||
|
||||
rijndael_tables:
|
||||
$(CC) -o $(OBJDIR)/make_rijndael_tab rijndael_tables.c \
|
||||
$(DEFINES) $(INCLUDES) $(OBJDIR)/libfreebl.a
|
||||
$(OBJDIR)/make_rijndael_tab
|
||||
|
||||
ifdef MOZILLA_BSAFE_BUILD
|
||||
|
||||
private_export::
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
rm -f $(DIST)/lib/bsafe$(BSAFEVER).lib
|
||||
endif
|
||||
$(NSINSTALL) -R $(BSAFEPATH) $(DIST)/lib
|
||||
endif
|
||||
|
||||
ifdef USE_PURE_32
|
||||
vpath %.h $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
vpath %.c $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
vpath %.S $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
vpath %.s $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
vpath %.asm $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
INCLUDES += -I$(FREEBL_PARENT) -I$(FREEBL_PARENT)/mpi
|
||||
else
|
||||
vpath %.h mpi
|
||||
vpath %.c mpi
|
||||
vpath %.S mpi
|
||||
vpath %.s mpi
|
||||
vpath %.asm mpi
|
||||
INCLUDES += -Impi
|
||||
endif
|
||||
|
||||
|
||||
DEFINES += -DMP_API_COMPATIBLE
|
||||
|
||||
MPI_USERS = dh.c pqg.c dsa.c rsa.c ec.c GFp_ecl.c
|
||||
|
||||
MPI_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_SRCS:.c=$(OBJ_SUFFIX)))
|
||||
MPI_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_USERS:.c=$(OBJ_SUFFIX)))
|
||||
|
||||
$(MPI_OBJS): $(MPI_HDRS)
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c
|
||||
|
||||
$(OBJDIR)/ldvector$(OBJ_SUFFIX) $(OBJDIR)/loader$(OBJ_SUFFIX) : loader.h
|
||||
|
||||
ifeq ($(SYSV_SPARC),1)
|
||||
|
||||
$(OBJDIR)/mpv_sparcv8.o $(OBJDIR)/montmulfv8.o : $(OBJDIR)/%.o : %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
|
||||
|
||||
$(OBJDIR)/mpv_sparcv9.o $(OBJDIR)/montmulfv9.o : $(OBJDIR)/%.o : %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
|
||||
|
||||
$(OBJDIR)/mpmontg.o: mpmontg.c montmulf.h
|
||||
|
||||
endif
|
||||
|
||||
ifdef FREEBL_EXTENDED_BUILD
|
||||
|
||||
PURE32DIR = $(OBJDIR)/$(OS_TARGET)pure32
|
||||
ALL_TRASH += $(PURE32DIR)
|
||||
|
||||
FILES2LN = \
|
||||
$(wildcard *.tab) \
|
||||
$(wildcard mapfile.*) \
|
||||
Makefile manifest.mn config.mk
|
||||
|
||||
LINKEDFILES = $(addprefix $(PURE32DIR)/, $(FILES2LN))
|
||||
|
||||
CDDIR := $(shell pwd)
|
||||
|
||||
$(PURE32DIR):
|
||||
-mkdir $(PURE32DIR)
|
||||
-ln -s $(CDDIR)/mpi $(PURE32DIR)
|
||||
|
||||
$(LINKEDFILES) : $(PURE32DIR)/% : %
|
||||
ln -s $(CDDIR)/$* $(PURE32DIR)
|
||||
|
||||
libs::
|
||||
$(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_HYBRID=1 libs
|
||||
|
||||
libs:: $(PURE32DIR) $(LINKEDFILES)
|
||||
cd $(PURE32DIR) && $(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_PURE_32=1 FREEBL_PARENT=$(CDDIR) CORE_DEPTH=$(CDDIR)/$(CORE_DEPTH) libs
|
||||
|
||||
release_md::
|
||||
$(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_HYBRID=1 $@
|
||||
cd $(PURE32DIR) && $(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_PURE_32=1 FREEBL_PARENT=$(CDDIR) CORE_DEPTH=$(CDDIR)/$(CORE_DEPTH) $@
|
||||
|
||||
endif
|
||||
@@ -1,383 +0,0 @@
|
||||
/*
|
||||
* aeskeywrap.c - implement AES Key Wrap algorithm from RFC 3394
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2002, 2003 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: aeskeywrap.c,v 1.1 2003-01-14 22:16:04 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "prcpucfg.h"
|
||||
#if defined(IS_LITTLE_ENDIAN) || defined(SHA_NO_LONG_LONG)
|
||||
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 0
|
||||
#else
|
||||
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 1
|
||||
#endif
|
||||
#include "prtypes.h" /* for PRUintXX */
|
||||
#include "secport.h" /* for PORT_XXX */
|
||||
#include "secerr.h"
|
||||
#include "blapi.h" /* for AES_ functions */
|
||||
|
||||
|
||||
struct AESKeyWrapContextStr {
|
||||
AESContext * aescx;
|
||||
unsigned char iv[AES_KEY_WRAP_IV_BYTES];
|
||||
};
|
||||
|
||||
/******************************************/
|
||||
/*
|
||||
** AES key wrap algorithm, RFC 3394
|
||||
*/
|
||||
|
||||
/*
|
||||
** Create a new AES context suitable for AES encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "keylen" the number of bytes of key data (16, 24, or 32)
|
||||
*/
|
||||
extern AESKeyWrapContext *
|
||||
AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv,
|
||||
int encrypt, unsigned int keylen)
|
||||
{
|
||||
AESKeyWrapContext * cx = PORT_ZNew(AESKeyWrapContext);
|
||||
if (!cx)
|
||||
return NULL; /* error is already set */
|
||||
cx->aescx = AES_CreateContext(key, NULL, NSS_AES, encrypt, keylen,
|
||||
AES_BLOCK_SIZE);
|
||||
if (!cx->aescx) {
|
||||
PORT_Free(cx);
|
||||
return NULL; /* error should already be set */
|
||||
}
|
||||
if (iv) {
|
||||
memcpy(cx->iv, iv, AES_KEY_WRAP_IV_BYTES);
|
||||
} else {
|
||||
memset(cx->iv, 0xA6, AES_KEY_WRAP_IV_BYTES);
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy a AES KeyWrap context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void
|
||||
AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
if (cx->aescx)
|
||||
AES_DestroyContext(cx->aescx, PR_TRUE);
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
|
||||
#if !BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
|
||||
/* The AES Key Wrap algorithm has 64-bit values that are ALWAYS big-endian
|
||||
** (Most significant byte first) in memory. The only ALU operations done
|
||||
** on them are increment, decrement, and XOR. So, on little-endian CPUs,
|
||||
** and on CPUs that lack 64-bit registers, these big-endian 64-bit operations
|
||||
** are simulated in the following code. This is thought to be faster and
|
||||
** simpler than trying to convert the data to little-endian and back.
|
||||
*/
|
||||
|
||||
/* A and T point to two 64-bit values stored most signficant byte first
|
||||
** (big endian). This function increments the 64-bit value T, and then
|
||||
** XORs it with A, changing A.
|
||||
*/
|
||||
static void
|
||||
increment_and_xor(unsigned char *A, unsigned char *T)
|
||||
{
|
||||
if (!++T[7])
|
||||
if (!++T[6])
|
||||
if (!++T[5])
|
||||
if (!++T[4])
|
||||
if (!++T[3])
|
||||
if (!++T[2])
|
||||
if (!++T[1])
|
||||
++T[0];
|
||||
|
||||
A[0] ^= T[0];
|
||||
A[1] ^= T[1];
|
||||
A[2] ^= T[2];
|
||||
A[3] ^= T[3];
|
||||
A[4] ^= T[4];
|
||||
A[5] ^= T[5];
|
||||
A[6] ^= T[6];
|
||||
A[7] ^= T[7];
|
||||
}
|
||||
|
||||
/* A and T point to two 64-bit values stored most signficant byte first
|
||||
** (big endian). This function XORs T with A, giving a new A, then
|
||||
** decrements the 64-bit value T.
|
||||
*/
|
||||
static void
|
||||
xor_and_decrement(unsigned char *A, unsigned char *T)
|
||||
{
|
||||
A[0] ^= T[0];
|
||||
A[1] ^= T[1];
|
||||
A[2] ^= T[2];
|
||||
A[3] ^= T[3];
|
||||
A[4] ^= T[4];
|
||||
A[5] ^= T[5];
|
||||
A[6] ^= T[6];
|
||||
A[7] ^= T[7];
|
||||
|
||||
if (!T[7]--)
|
||||
if (!T[6]--)
|
||||
if (!T[5]--)
|
||||
if (!T[4]--)
|
||||
if (!T[3]--)
|
||||
if (!T[2]--)
|
||||
if (!T[1]--)
|
||||
T[0]--;
|
||||
|
||||
}
|
||||
|
||||
/* Given an unsigned long t (in host byte order), store this value as a
|
||||
** 64-bit big-endian value (MSB first) in *pt.
|
||||
*/
|
||||
static void
|
||||
set_t(unsigned char *pt, unsigned long t)
|
||||
{
|
||||
pt[7] = (unsigned char)t; t >>= 8;
|
||||
pt[6] = (unsigned char)t; t >>= 8;
|
||||
pt[5] = (unsigned char)t; t >>= 8;
|
||||
pt[4] = (unsigned char)t; t >>= 8;
|
||||
pt[3] = (unsigned char)t; t >>= 8;
|
||||
pt[2] = (unsigned char)t; t >>= 8;
|
||||
pt[1] = (unsigned char)t; t >>= 8;
|
||||
pt[0] = (unsigned char)t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Perform AES key wrap.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the encrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
extern SECStatus
|
||||
AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
|
||||
unsigned int *pOutputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint64 * R = NULL;
|
||||
unsigned int nBlocks;
|
||||
unsigned int i, j;
|
||||
unsigned int aesLen = AES_BLOCK_SIZE;
|
||||
unsigned int outLen = inputLen + AES_KEY_WRAP_BLOCK_SIZE;
|
||||
SECStatus s = SECFailure;
|
||||
/* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
||||
PRUint64 t;
|
||||
PRUint64 B[2];
|
||||
|
||||
#define A B[0]
|
||||
|
||||
/* Check args */
|
||||
if (!inputLen || 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
#ifdef maybe
|
||||
if (!output && pOutputLen) { /* caller is asking for output size */
|
||||
*pOutputLen = outLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
if (maxOutputLen < outLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
if (cx == NULL || output == NULL || input == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return s;
|
||||
}
|
||||
nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
||||
R = PORT_NewArray(PRUint64, nBlocks + 1);
|
||||
if (!R)
|
||||
return s; /* error is already set. */
|
||||
/*
|
||||
** 1) Initialize variables.
|
||||
*/
|
||||
memcpy(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
||||
memcpy(&R[1], input, inputLen);
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
t = 0;
|
||||
#else
|
||||
memset(&t, 0, sizeof t);
|
||||
#endif
|
||||
/*
|
||||
** 2) Calculate intermediate values.
|
||||
*/
|
||||
for (j = 0; j < 6; ++j) {
|
||||
for (i = 1; i <= nBlocks; ++i) {
|
||||
B[1] = R[i];
|
||||
s = AES_Encrypt(cx->aescx, (unsigned char *)B, &aesLen,
|
||||
sizeof B, (unsigned char *)B, sizeof B);
|
||||
if (s != SECSuccess)
|
||||
break;
|
||||
R[i] = B[1];
|
||||
/* here, increment t and XOR A with t (in big endian order); */
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
A ^= ++t;
|
||||
#else
|
||||
increment_and_xor((unsigned char *)&A, (unsigned char *)&t);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*
|
||||
** 3) Output the results.
|
||||
*/
|
||||
if (s == SECSuccess) {
|
||||
R[0] = A;
|
||||
memcpy(output, &R[0], outLen);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = outLen;
|
||||
} else if (pOutputLen) {
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
PORT_ZFree(R, outLen);
|
||||
return s;
|
||||
}
|
||||
#undef A
|
||||
|
||||
/*
|
||||
** Perform AES key unwrap.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the decrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
extern SECStatus
|
||||
AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
|
||||
unsigned int *pOutputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint64 * R = NULL;
|
||||
unsigned int nBlocks;
|
||||
unsigned int i, j;
|
||||
unsigned int aesLen = AES_BLOCK_SIZE;
|
||||
unsigned int outLen;
|
||||
SECStatus s = SECFailure;
|
||||
/* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
||||
PRUint64 t;
|
||||
PRUint64 B[2];
|
||||
|
||||
#define A B[0]
|
||||
|
||||
/* Check args */
|
||||
if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
|
||||
0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
outLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
|
||||
#ifdef maybe
|
||||
if (!output && pOutputLen) { /* caller is asking for output size */
|
||||
*pOutputLen = outLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
if (maxOutputLen < outLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
if (cx == NULL || output == NULL || input == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return s;
|
||||
}
|
||||
nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
||||
R = PORT_NewArray(PRUint64, nBlocks);
|
||||
if (!R)
|
||||
return s; /* error is already set. */
|
||||
nBlocks--;
|
||||
/*
|
||||
** 1) Initialize variables.
|
||||
*/
|
||||
memcpy(&R[0], input, inputLen);
|
||||
A = R[0];
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
t = 6UL * nBlocks;
|
||||
#else
|
||||
set_t((unsigned char *)&t, 6UL * nBlocks);
|
||||
#endif
|
||||
/*
|
||||
** 2) Calculate intermediate values.
|
||||
*/
|
||||
for (j = 0; j < 6; ++j) {
|
||||
for (i = nBlocks; i; --i) {
|
||||
/* here, XOR A with t (in big endian order) and decrement t; */
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
A ^= t--;
|
||||
#else
|
||||
xor_and_decrement((unsigned char *)&A, (unsigned char *)&t);
|
||||
#endif
|
||||
B[1] = R[i];
|
||||
s = AES_Decrypt(cx->aescx, (unsigned char *)B, &aesLen,
|
||||
sizeof B, (unsigned char *)B, sizeof B);
|
||||
if (s != SECSuccess)
|
||||
break;
|
||||
R[i] = B[1];
|
||||
}
|
||||
}
|
||||
/*
|
||||
** 3) Output the results.
|
||||
*/
|
||||
if (s == SECSuccess) {
|
||||
int bad = memcmp(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
||||
if (!bad) {
|
||||
memcpy(output, &R[1], outLen);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = outLen;
|
||||
} else {
|
||||
PORT_SetError(SEC_ERROR_BAD_DATA);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
} else if (pOutputLen) {
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
PORT_ZFree(R, inputLen);
|
||||
return s;
|
||||
}
|
||||
#undef A
|
||||
@@ -1,493 +0,0 @@
|
||||
/*
|
||||
* alg2268.c - implementation of the algorithm in RFC 2268
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: alg2268.c,v 1.4 2002-11-16 06:09:57 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secerr.h"
|
||||
#ifdef XP_UNIX_XXX
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** RC2 symmetric block cypher
|
||||
*/
|
||||
|
||||
typedef SECStatus (rc2Func)(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
/* forward declarations */
|
||||
static rc2Func rc2_EncryptECB;
|
||||
static rc2Func rc2_DecryptECB;
|
||||
static rc2Func rc2_EncryptCBC;
|
||||
static rc2Func rc2_DecryptCBC;
|
||||
|
||||
typedef union {
|
||||
PRUint32 l[2];
|
||||
PRUint16 s[4];
|
||||
PRUint8 b[8];
|
||||
} RC2Block;
|
||||
|
||||
struct RC2ContextStr {
|
||||
union {
|
||||
PRUint8 Kb[128];
|
||||
PRUint16 Kw[64];
|
||||
} u;
|
||||
RC2Block iv;
|
||||
rc2Func *enc;
|
||||
rc2Func *dec;
|
||||
};
|
||||
|
||||
#define B u.Kb
|
||||
#define K u.Kw
|
||||
#define BYTESWAP(x) ((x) << 8 | (x) >> 8)
|
||||
#define SWAPK(i) cx->K[i] = (tmpS = cx->K[i], BYTESWAP(tmpS))
|
||||
#define RC2_BLOCK_SIZE 8
|
||||
|
||||
#define LOAD_HARD(R) \
|
||||
R[0] = (PRUint16)input[1] << 8 | input[0]; \
|
||||
R[1] = (PRUint16)input[3] << 8 | input[2]; \
|
||||
R[2] = (PRUint16)input[5] << 8 | input[4]; \
|
||||
R[3] = (PRUint16)input[7] << 8 | input[6];
|
||||
#define LOAD_EASY(R) \
|
||||
R[0] = ((PRUint16 *)input)[0]; \
|
||||
R[1] = ((PRUint16 *)input)[1]; \
|
||||
R[2] = ((PRUint16 *)input)[2]; \
|
||||
R[3] = ((PRUint16 *)input)[3];
|
||||
#define STORE_HARD(R) \
|
||||
output[0] = (PRUint8)(R[0]); output[1] = (PRUint8)(R[0] >> 8); \
|
||||
output[2] = (PRUint8)(R[1]); output[3] = (PRUint8)(R[1] >> 8); \
|
||||
output[4] = (PRUint8)(R[2]); output[5] = (PRUint8)(R[2] >> 8); \
|
||||
output[6] = (PRUint8)(R[3]); output[7] = (PRUint8)(R[3] >> 8);
|
||||
#define STORE_EASY(R) \
|
||||
((PRUint16 *)output)[0] = R[0]; \
|
||||
((PRUint16 *)output)[1] = R[1]; \
|
||||
((PRUint16 *)output)[2] = R[2]; \
|
||||
((PRUint16 *)output)[3] = R[3];
|
||||
|
||||
#if defined (_X86_)
|
||||
#define LOAD(R) LOAD_EASY(R)
|
||||
#define STORE(R) STORE_EASY(R)
|
||||
#elif !defined(IS_LITTLE_ENDIAN)
|
||||
#define LOAD(R) LOAD_HARD(R)
|
||||
#define STORE(R) STORE_HARD(R)
|
||||
#else
|
||||
#define LOAD(R) if ((ptrdiff_t)input & 1) { LOAD_HARD(R) } else { LOAD_EASY(R) }
|
||||
#define STORE(R) if ((ptrdiff_t)input & 1) { STORE_HARD(R) } else { STORE_EASY(R) }
|
||||
#endif
|
||||
|
||||
static const PRUint8 S[256] = {
|
||||
0331,0170,0371,0304,0031,0335,0265,0355,0050,0351,0375,0171,0112,0240,0330,0235,
|
||||
0306,0176,0067,0203,0053,0166,0123,0216,0142,0114,0144,0210,0104,0213,0373,0242,
|
||||
0027,0232,0131,0365,0207,0263,0117,0023,0141,0105,0155,0215,0011,0201,0175,0062,
|
||||
0275,0217,0100,0353,0206,0267,0173,0013,0360,0225,0041,0042,0134,0153,0116,0202,
|
||||
0124,0326,0145,0223,0316,0140,0262,0034,0163,0126,0300,0024,0247,0214,0361,0334,
|
||||
0022,0165,0312,0037,0073,0276,0344,0321,0102,0075,0324,0060,0243,0074,0266,0046,
|
||||
0157,0277,0016,0332,0106,0151,0007,0127,0047,0362,0035,0233,0274,0224,0103,0003,
|
||||
0370,0021,0307,0366,0220,0357,0076,0347,0006,0303,0325,0057,0310,0146,0036,0327,
|
||||
0010,0350,0352,0336,0200,0122,0356,0367,0204,0252,0162,0254,0065,0115,0152,0052,
|
||||
0226,0032,0322,0161,0132,0025,0111,0164,0113,0237,0320,0136,0004,0030,0244,0354,
|
||||
0302,0340,0101,0156,0017,0121,0313,0314,0044,0221,0257,0120,0241,0364,0160,0071,
|
||||
0231,0174,0072,0205,0043,0270,0264,0172,0374,0002,0066,0133,0045,0125,0227,0061,
|
||||
0055,0135,0372,0230,0343,0212,0222,0256,0005,0337,0051,0020,0147,0154,0272,0311,
|
||||
0323,0000,0346,0317,0341,0236,0250,0054,0143,0026,0001,0077,0130,0342,0211,0251,
|
||||
0015,0070,0064,0033,0253,0063,0377,0260,0273,0110,0014,0137,0271,0261,0315,0056,
|
||||
0305,0363,0333,0107,0345,0245,0234,0167,0012,0246,0040,0150,0376,0177,0301,0255
|
||||
};
|
||||
|
||||
/*
|
||||
** Create a new RC2 context suitable for RC2 encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "len" the number of bytes of key data
|
||||
** "iv" is the CBC initialization vector (if mode is NSS_RC2_CBC)
|
||||
** "mode" one of NSS_RC2 or NSS_RC2_CBC
|
||||
** "effectiveKeyLen" in bytes, not bits.
|
||||
**
|
||||
** When mode is set to NSS_RC2_CBC the RC2 cipher is run in "cipher block
|
||||
** chaining" mode.
|
||||
*/
|
||||
RC2Context *
|
||||
RC2_CreateContext(const unsigned char *key, unsigned int len,
|
||||
const unsigned char *input, int mode, unsigned efLen8)
|
||||
{
|
||||
RC2Context *cx;
|
||||
PRUint8 *L,*L2;
|
||||
int i;
|
||||
#if !defined(IS_LITTLE_ENDIAN)
|
||||
PRUint16 tmpS;
|
||||
#endif
|
||||
PRUint8 tmpB;
|
||||
|
||||
if (!key || len == 0 || len > (sizeof cx->B) || efLen8 > (sizeof cx->B)) {
|
||||
return NULL;
|
||||
}
|
||||
if (mode == NSS_RC2) {
|
||||
/* groovy */
|
||||
} else if (mode == NSS_RC2_CBC) {
|
||||
if (!input) {
|
||||
return NULL; /* not groovy */
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cx = PORT_ZNew(RC2Context);
|
||||
if (!cx)
|
||||
return cx;
|
||||
|
||||
if (mode == NSS_RC2_CBC) {
|
||||
cx->enc = & rc2_EncryptCBC;
|
||||
cx->dec = & rc2_DecryptCBC;
|
||||
LOAD(cx->iv.s);
|
||||
} else {
|
||||
cx->enc = & rc2_EncryptECB;
|
||||
cx->dec = & rc2_DecryptECB;
|
||||
}
|
||||
|
||||
/* Step 0. Copy key into table. */
|
||||
memcpy(cx->B, key, len);
|
||||
|
||||
/* Step 1. Compute all values to the right of the key. */
|
||||
L2 = cx->B;
|
||||
L = L2 + len;
|
||||
tmpB = L[-1];
|
||||
for (i = (sizeof cx->B) - len; i > 0; --i) {
|
||||
*L++ = tmpB = S[ (PRUint8)(tmpB + *L2++) ];
|
||||
}
|
||||
|
||||
/* step 2. Adjust left most byte of effective key. */
|
||||
i = (sizeof cx->B) - efLen8;
|
||||
L = cx->B + i;
|
||||
*L = tmpB = S[*L]; /* mask is always 0xff */
|
||||
|
||||
/* step 3. Recompute all values to the left of effective key. */
|
||||
L2 = --L + efLen8;
|
||||
while(L >= cx->B) {
|
||||
*L-- = tmpB = S[ tmpB ^ *L2-- ];
|
||||
}
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN)
|
||||
for (i = 63; i >= 0; --i) {
|
||||
SWAPK(i); /* candidate for unrolling */
|
||||
}
|
||||
#endif
|
||||
return cx;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy an RC2 encryption/decryption context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
void
|
||||
RC2_DestroyContext(RC2Context *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit) {
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ROL(x,k) (x << k | x >> (16-k))
|
||||
#define MIX(j) \
|
||||
R0 = R0 + cx->K[ 4*j+0] + (R3 & R2) + (~R3 & R1); R0 = ROL(R0,1);\
|
||||
R1 = R1 + cx->K[ 4*j+1] + (R0 & R3) + (~R0 & R2); R1 = ROL(R1,2);\
|
||||
R2 = R2 + cx->K[ 4*j+2] + (R1 & R0) + (~R1 & R3); R2 = ROL(R2,3);\
|
||||
R3 = R3 + cx->K[ 4*j+3] + (R2 & R1) + (~R2 & R0); R3 = ROL(R3,5)
|
||||
#define MASH \
|
||||
R0 = R0 + cx->K[R3 & 63];\
|
||||
R1 = R1 + cx->K[R0 & 63];\
|
||||
R2 = R2 + cx->K[R1 & 63];\
|
||||
R3 = R3 + cx->K[R2 & 63]
|
||||
|
||||
/* Encrypt one block */
|
||||
static void
|
||||
rc2_Encrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
|
||||
{
|
||||
register PRUint16 R0, R1, R2, R3;
|
||||
|
||||
/* step 1. Initialize input. */
|
||||
R0 = input->s[0];
|
||||
R1 = input->s[1];
|
||||
R2 = input->s[2];
|
||||
R3 = input->s[3];
|
||||
|
||||
/* step 2. Expand Key (already done, in context) */
|
||||
/* step 3. j = 0 */
|
||||
/* step 4. Perform 5 mixing rounds. */
|
||||
|
||||
MIX(0);
|
||||
MIX(1);
|
||||
MIX(2);
|
||||
MIX(3);
|
||||
MIX(4);
|
||||
|
||||
/* step 5. Perform 1 mashing round. */
|
||||
MASH;
|
||||
|
||||
/* step 6. Perform 6 mixing rounds. */
|
||||
|
||||
MIX(5);
|
||||
MIX(6);
|
||||
MIX(7);
|
||||
MIX(8);
|
||||
MIX(9);
|
||||
MIX(10);
|
||||
|
||||
/* step 7. Perform 1 mashing round. */
|
||||
MASH;
|
||||
|
||||
/* step 8. Perform 5 mixing rounds. */
|
||||
|
||||
MIX(11);
|
||||
MIX(12);
|
||||
MIX(13);
|
||||
MIX(14);
|
||||
MIX(15);
|
||||
|
||||
/* output results */
|
||||
output->s[0] = R0;
|
||||
output->s[1] = R1;
|
||||
output->s[2] = R2;
|
||||
output->s[3] = R3;
|
||||
}
|
||||
|
||||
#define ROR(x,k) (x >> k | x << (16-k))
|
||||
#define R_MIX(j) \
|
||||
R3 = ROR(R3,5); R3 = R3 - cx->K[ 4*j+3] - (R2 & R1) - (~R2 & R0); \
|
||||
R2 = ROR(R2,3); R2 = R2 - cx->K[ 4*j+2] - (R1 & R0) - (~R1 & R3); \
|
||||
R1 = ROR(R1,2); R1 = R1 - cx->K[ 4*j+1] - (R0 & R3) - (~R0 & R2); \
|
||||
R0 = ROR(R0,1); R0 = R0 - cx->K[ 4*j+0] - (R3 & R2) - (~R3 & R1)
|
||||
#define R_MASH \
|
||||
R3 = R3 - cx->K[R2 & 63];\
|
||||
R2 = R2 - cx->K[R1 & 63];\
|
||||
R1 = R1 - cx->K[R0 & 63];\
|
||||
R0 = R0 - cx->K[R3 & 63]
|
||||
|
||||
/* Encrypt one block */
|
||||
static void
|
||||
rc2_Decrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
|
||||
{
|
||||
register PRUint16 R0, R1, R2, R3;
|
||||
|
||||
/* step 1. Initialize input. */
|
||||
R0 = input->s[0];
|
||||
R1 = input->s[1];
|
||||
R2 = input->s[2];
|
||||
R3 = input->s[3];
|
||||
|
||||
/* step 2. Expand Key (already done, in context) */
|
||||
/* step 3. j = 63 */
|
||||
/* step 4. Perform 5 r_mixing rounds. */
|
||||
R_MIX(15);
|
||||
R_MIX(14);
|
||||
R_MIX(13);
|
||||
R_MIX(12);
|
||||
R_MIX(11);
|
||||
|
||||
/* step 5. Perform 1 r_mashing round. */
|
||||
R_MASH;
|
||||
|
||||
/* step 6. Perform 6 r_mixing rounds. */
|
||||
R_MIX(10);
|
||||
R_MIX(9);
|
||||
R_MIX(8);
|
||||
R_MIX(7);
|
||||
R_MIX(6);
|
||||
R_MIX(5);
|
||||
|
||||
/* step 7. Perform 1 r_mashing round. */
|
||||
R_MASH;
|
||||
|
||||
/* step 8. Perform 5 r_mixing rounds. */
|
||||
R_MIX(4);
|
||||
R_MIX(3);
|
||||
R_MIX(2);
|
||||
R_MIX(1);
|
||||
R_MIX(0);
|
||||
|
||||
/* output results */
|
||||
output->s[0] = R0;
|
||||
output->s[1] = R1;
|
||||
output->s[2] = R2;
|
||||
output->s[3] = R3;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_EncryptECB(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Encrypt1Block(cx, &iBlock, &iBlock);
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_DecryptECB(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Decrypt1Block(cx, &iBlock, &iBlock);
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_EncryptCBC(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
|
||||
LOAD(iBlock.s)
|
||||
iBlock.l[0] ^= cx->iv.l[0];
|
||||
iBlock.l[1] ^= cx->iv.l[1];
|
||||
rc2_Encrypt1Block(cx, &iBlock, &iBlock);
|
||||
cx->iv = iBlock;
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_DecryptCBC(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
RC2Block oBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Decrypt1Block(cx, &oBlock, &iBlock);
|
||||
oBlock.l[0] ^= cx->iv.l[0];
|
||||
oBlock.l[1] ^= cx->iv.l[1];
|
||||
cx->iv = iBlock;
|
||||
STORE(oBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Perform RC2 encryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the encrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus RC2_Encrypt(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
if (inputLen) {
|
||||
if (inputLen % RC2_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = (*cx->enc)(cx, output, input, inputLen);
|
||||
}
|
||||
if (rv == SECSuccess) {
|
||||
*outputLen = inputLen;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC2 decryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the decrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus RC2_Decrypt(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
if (inputLen) {
|
||||
if (inputLen % RC2_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = (*cx->dec)(cx, output, input, inputLen);
|
||||
}
|
||||
if (rv == SECSuccess) {
|
||||
*outputLen = inputLen;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* arcfive.c - stubs for RC5 - NOT a working implementation!
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: arcfive.c,v 1.3 2002-11-16 06:09:57 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "blapi.h"
|
||||
#include "prerror.h"
|
||||
|
||||
/******************************************/
|
||||
/*
|
||||
** RC5 symmetric block cypher -- 64-bit block size
|
||||
*/
|
||||
|
||||
/*
|
||||
** Create a new RC5 context suitable for RC5 encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "len" the number of bytes of key data
|
||||
** "iv" is the CBC initialization vector (if mode is NSS_RC5_CBC)
|
||||
** "mode" one of NSS_RC5 or NSS_RC5_CBC
|
||||
**
|
||||
** When mode is set to NSS_RC5_CBC the RC5 cipher is run in "cipher block
|
||||
** chaining" mode.
|
||||
*/
|
||||
RC5Context *
|
||||
RC5_CreateContext(const SECItem *key, unsigned int rounds,
|
||||
unsigned int wordSize, const unsigned char *iv, int mode)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy an RC5 encryption/decryption context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
void
|
||||
RC5_DestroyContext(RC5Context *cx, PRBool freeit)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC5 encryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the encrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus
|
||||
RC5_Encrypt(RC5Context *cx, unsigned char *output, unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC5 decryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the decrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus
|
||||
RC5_Decrypt(RC5Context *cx, unsigned char *output, unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
@@ -1,567 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "blapi.h"
|
||||
|
||||
/* Architecture-dependent defines */
|
||||
|
||||
#if defined(SOLARIS) || defined(HPUX) || defined(i386) || defined(IRIX)
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
#define CONVERT_TO_WORDS
|
||||
#endif
|
||||
|
||||
#if defined(AIX) || defined(OSF1)
|
||||
/* Treat array variables as longs, not bytes */
|
||||
#define USE_LONG
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
#undef WORD
|
||||
#define WORD ARC4WORD
|
||||
#endif
|
||||
|
||||
#if defined(NSS_USE_HYBRID) && !defined(SOLARIS) && !defined(NSS_USE_64)
|
||||
typedef unsigned long long WORD;
|
||||
#else
|
||||
typedef unsigned long WORD;
|
||||
#endif
|
||||
#define WORDSIZE sizeof(WORD)
|
||||
|
||||
#ifdef USE_LONG
|
||||
typedef unsigned long Stype;
|
||||
#else
|
||||
typedef PRUint8 Stype;
|
||||
#endif
|
||||
|
||||
#define ARCFOUR_STATE_SIZE 256
|
||||
|
||||
#define MASK1BYTE (WORD)(0xff)
|
||||
|
||||
#define SWAP(a, b) \
|
||||
tmp = a; \
|
||||
a = b; \
|
||||
b = tmp;
|
||||
|
||||
/*
|
||||
* State information for stream cipher.
|
||||
*/
|
||||
struct RC4ContextStr
|
||||
{
|
||||
Stype S[ARCFOUR_STATE_SIZE];
|
||||
PRUint8 i;
|
||||
PRUint8 j;
|
||||
};
|
||||
|
||||
/*
|
||||
* array indices [0..255] to initialize cx->S array (faster than loop).
|
||||
*/
|
||||
static const Stype Kinit[256] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize a new generator.
|
||||
*/
|
||||
RC4Context *
|
||||
RC4_CreateContext(const unsigned char *key, int len)
|
||||
{
|
||||
int i;
|
||||
PRUint8 j, tmp;
|
||||
RC4Context *cx;
|
||||
PRUint8 K[256];
|
||||
PRUint8 *L;
|
||||
/* verify the key length. */
|
||||
PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE);
|
||||
if (len < 0 || len >= ARCFOUR_STATE_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
/* Create space for the context. */
|
||||
cx = (RC4Context *)PORT_ZAlloc(sizeof(RC4Context));
|
||||
if (cx == NULL) {
|
||||
PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
/* Initialize the state using array indices. */
|
||||
memcpy(cx->S, Kinit, sizeof cx->S);
|
||||
/* Fill in K repeatedly with values from key. */
|
||||
L = K;
|
||||
for (i = sizeof K; i > len; i-= len) {
|
||||
memcpy(L, key, len);
|
||||
L += len;
|
||||
}
|
||||
memcpy(L, key, i);
|
||||
/* Stir the state of the generator. At this point it is assumed
|
||||
* that the key is the size of the state buffer. If this is not
|
||||
* the case, the key bytes are repeated to fill the buffer.
|
||||
*/
|
||||
j = 0;
|
||||
#define ARCFOUR_STATE_STIR(ii) \
|
||||
j = j + cx->S[ii] + K[ii]; \
|
||||
SWAP(cx->S[ii], cx->S[j]);
|
||||
for (i=0; i<ARCFOUR_STATE_SIZE; i++) {
|
||||
ARCFOUR_STATE_STIR(i);
|
||||
}
|
||||
cx->i = 0;
|
||||
cx->j = 0;
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
RC4_DestroyContext(RC4Context *cx, PRBool freeit)
|
||||
{
|
||||
if (freeit)
|
||||
PORT_ZFree(cx, sizeof(*cx));
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the next byte in the stream.
|
||||
*/
|
||||
#define ARCFOUR_NEXT_BYTE() \
|
||||
tmpSi = cx->S[++tmpi]; \
|
||||
tmpj += tmpSi; \
|
||||
tmpSj = cx->S[tmpj]; \
|
||||
cx->S[tmpi] = tmpSj; \
|
||||
cx->S[tmpj] = tmpSi; \
|
||||
t = tmpSi + tmpSj;
|
||||
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/*
|
||||
* Straight RC4 op. No optimization.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_no_opt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint8 t;
|
||||
Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
unsigned int index;
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
for (index=0; index < inputLen; index++) {
|
||||
/* Generate next byte from stream. */
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
/* output = next stream byte XOR next input byte */
|
||||
output[index] = cx->S[t] ^ input[index];
|
||||
}
|
||||
*outputLen = inputLen;
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONVERT_TO_WORDS
|
||||
/*
|
||||
* Byte-at-a-time RC4, unrolling the loop into 8 pieces.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_unrolled(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint8 t;
|
||||
Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
int index;
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
for (index = inputLen / 8; index-- > 0; input += 8, output += 8) {
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[0] = cx->S[t] ^ input[0];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[1] = cx->S[t] ^ input[1];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[2] = cx->S[t] ^ input[2];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[3] = cx->S[t] ^ input[3];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[4] = cx->S[t] ^ input[4];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[5] = cx->S[t] ^ input[5];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[6] = cx->S[t] ^ input[6];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[7] = cx->S[t] ^ input[7];
|
||||
}
|
||||
index = inputLen % 8;
|
||||
if (index) {
|
||||
input += index;
|
||||
output += index;
|
||||
switch (index) {
|
||||
case 7:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-7] = cx->S[t] ^ input[-7]; /* FALLTHRU */
|
||||
case 6:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-6] = cx->S[t] ^ input[-6]; /* FALLTHRU */
|
||||
case 5:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-5] = cx->S[t] ^ input[-5]; /* FALLTHRU */
|
||||
case 4:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-4] = cx->S[t] ^ input[-4]; /* FALLTHRU */
|
||||
case 3:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-3] = cx->S[t] ^ input[-3]; /* FALLTHRU */
|
||||
case 2:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-2] = cx->S[t] ^ input[-2]; /* FALLTHRU */
|
||||
case 1:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-1] = cx->S[t] ^ input[-1]; /* FALLTHRU */
|
||||
default:
|
||||
/* FALLTHRU */
|
||||
; /* hp-ux build breaks without this */
|
||||
}
|
||||
}
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
*outputLen = inputLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT4BYTES_L(n) \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n ); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 8); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24);
|
||||
#else
|
||||
#define ARCFOUR_NEXT4BYTES_B(n) \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 8); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n );
|
||||
#endif
|
||||
|
||||
#if (defined(NSS_USE_HYBRID) && !defined(SOLARIS)) || defined(NSS_USE_64)
|
||||
/* 64-bit wordsize */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); ARCFOUR_NEXT4BYTES_L(32); }
|
||||
#else
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(32); ARCFOUR_NEXT4BYTES_B(0); }
|
||||
#endif
|
||||
#else
|
||||
/* 32-bit wordsize */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); }
|
||||
#else
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(0); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define RSH <<
|
||||
#define LSH >>
|
||||
#else
|
||||
#define RSH >>
|
||||
#define LSH <<
|
||||
#endif
|
||||
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/*
|
||||
* Convert input and output buffers to words before performing
|
||||
* RC4 operations.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_wordconv(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
ptrdiff_t inOffset = (ptrdiff_t)input % WORDSIZE;
|
||||
ptrdiff_t outOffset = (ptrdiff_t)output % WORDSIZE;
|
||||
register WORD streamWord, mask;
|
||||
register WORD *pInWord, *pOutWord;
|
||||
register WORD inWord, nextInWord;
|
||||
PRUint8 t;
|
||||
register Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
unsigned int byteCount;
|
||||
unsigned int bufShift, invBufShift;
|
||||
int i;
|
||||
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (inputLen < 2*WORDSIZE) {
|
||||
/* Ignore word conversion, do byte-at-a-time */
|
||||
return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
}
|
||||
*outputLen = inputLen;
|
||||
pInWord = (WORD *)(input - inOffset);
|
||||
if (inOffset < outOffset) {
|
||||
bufShift = 8*(outOffset - inOffset);
|
||||
invBufShift = 8*WORDSIZE - bufShift;
|
||||
} else {
|
||||
invBufShift = 8*(inOffset - outOffset);
|
||||
bufShift = 8*WORDSIZE - invBufShift;
|
||||
}
|
||||
/*****************************************************************/
|
||||
/* Step 1: */
|
||||
/* If the first output word is partial, consume the bytes in the */
|
||||
/* first partial output word by loading one or two words of */
|
||||
/* input and shifting them accordingly. Otherwise, just load */
|
||||
/* in the first word of input. At the end of this block, at */
|
||||
/* least one partial word of input should ALWAYS be loaded. */
|
||||
/*****************************************************************/
|
||||
if (outOffset) {
|
||||
/* Generate input and stream words aligned relative to the
|
||||
* partial output buffer.
|
||||
*/
|
||||
byteCount = WORDSIZE - outOffset;
|
||||
pOutWord = (WORD *)(output - outOffset);
|
||||
mask = streamWord = 0;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
for (i = WORDSIZE - byteCount; i < WORDSIZE; i++) {
|
||||
#else
|
||||
for (i = byteCount - 1; i >= 0; --i) {
|
||||
#endif
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
streamWord |= (WORD)(cx->S[t]) << 8*i;
|
||||
mask |= MASK1BYTE << 8*i;
|
||||
} /* } */
|
||||
inWord = *pInWord++;
|
||||
/* If buffers are relatively misaligned, shift the bytes in inWord
|
||||
* to be aligned to the output buffer.
|
||||
*/
|
||||
nextInWord = 0;
|
||||
if (inOffset < outOffset) {
|
||||
/* Have more bytes than needed, shift remainder into nextInWord */
|
||||
nextInWord = inWord LSH 8*(inOffset + byteCount);
|
||||
inWord = inWord RSH bufShift;
|
||||
} else if (inOffset > outOffset) {
|
||||
/* Didn't get enough bytes from current input word, load another
|
||||
* word and then shift remainder into nextInWord.
|
||||
*/
|
||||
nextInWord = *pInWord++;
|
||||
inWord = (inWord LSH invBufShift) |
|
||||
(nextInWord RSH bufShift);
|
||||
nextInWord = nextInWord LSH invBufShift;
|
||||
}
|
||||
/* Store output of first partial word */
|
||||
*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
|
||||
/* Consumed byteCount bytes of input */
|
||||
inputLen -= byteCount;
|
||||
/* move to next word of output */
|
||||
pOutWord++;
|
||||
/* inWord has been consumed, but there may be bytes in nextInWord */
|
||||
inWord = nextInWord;
|
||||
} else {
|
||||
/* output is word-aligned */
|
||||
pOutWord = (WORD *)output;
|
||||
if (inOffset) {
|
||||
/* Input is not word-aligned. The first word load of input
|
||||
* will not produce a full word of input bytes, so one word
|
||||
* must be pre-loaded. The main loop below will load in the
|
||||
* next input word and shift some of its bytes into inWord
|
||||
* in order to create a full input word. Note that the main
|
||||
* loop must execute at least once because the input must
|
||||
* be at least two words.
|
||||
*/
|
||||
inWord = *pInWord++;
|
||||
inWord = inWord LSH invBufShift;
|
||||
} else {
|
||||
/* Input is word-aligned. The first word load of input
|
||||
* will produce a full word of input bytes, so nothing
|
||||
* needs to be loaded here.
|
||||
*/
|
||||
inWord = 0;
|
||||
}
|
||||
}
|
||||
/* Output buffer is aligned, inOffset is now measured relative to
|
||||
* outOffset (and not a word boundary).
|
||||
*/
|
||||
inOffset = (inOffset + WORDSIZE - outOffset) % WORDSIZE;
|
||||
/*****************************************************************/
|
||||
/* Step 2: main loop */
|
||||
/* At this point the output buffer is word-aligned. Any unused */
|
||||
/* bytes from above will be in inWord (shifted correctly). If */
|
||||
/* the input buffer is unaligned relative to the output buffer, */
|
||||
/* shifting has to be done. */
|
||||
/*****************************************************************/
|
||||
if (inOffset) {
|
||||
for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
|
||||
nextInWord = *pInWord++;
|
||||
inWord |= nextInWord RSH bufShift;
|
||||
nextInWord = nextInWord LSH invBufShift;
|
||||
ARCFOUR_NEXT_WORD();
|
||||
*pOutWord++ = inWord ^ streamWord;
|
||||
inWord = nextInWord;
|
||||
}
|
||||
if (inputLen == 0) {
|
||||
/* Nothing left to do. */
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
/* If the amount of remaining input is greater than the amount
|
||||
* bytes pulled from the current input word, need to do another
|
||||
* word load. What's left in inWord will be consumed in step 3.
|
||||
*/
|
||||
if (inputLen > WORDSIZE - inOffset)
|
||||
inWord |= *pInWord RSH bufShift;
|
||||
} else {
|
||||
for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
|
||||
inWord = *pInWord++;
|
||||
ARCFOUR_NEXT_WORD();
|
||||
*pOutWord++ = inWord ^ streamWord;
|
||||
}
|
||||
if (inputLen == 0) {
|
||||
/* Nothing left to do. */
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
} else {
|
||||
/* A partial input word remains at the tail. Load it. The
|
||||
* relevant bytes will be consumed in step 3.
|
||||
*/
|
||||
inWord = *pInWord;
|
||||
}
|
||||
}
|
||||
/*****************************************************************/
|
||||
/* Step 3: */
|
||||
/* A partial word of input remains, and it is already loaded */
|
||||
/* into nextInWord. Shift appropriately and consume the bytes */
|
||||
/* used in the partial word. */
|
||||
/*****************************************************************/
|
||||
mask = streamWord = 0;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
for (i = 0; i < inputLen; ++i) {
|
||||
#else
|
||||
for (i = WORDSIZE - 1; i >= WORDSIZE - inputLen; --i) {
|
||||
#endif
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
streamWord |= (WORD)(cx->S[t]) << 8*i;
|
||||
mask |= MASK1BYTE << 8*i;
|
||||
} /* } */
|
||||
*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
SECStatus
|
||||
RC4_Encrypt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#else
|
||||
/* Operate on bytes, but unroll the main loop */
|
||||
return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECStatus RC4_Decrypt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* decrypt and encrypt are same operation. */
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#else
|
||||
/* Operate on bytes, but unroll the main loop */
|
||||
return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef CONVERT_TO_WORDS
|
||||
#undef USE_LONG
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,336 +0,0 @@
|
||||
/*
|
||||
* blapit.h - public data structures for the crypto library
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: blapit.h,v 1.10 2003-03-29 00:18:18 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _BLAPIT_H_
|
||||
#define _BLAPIT_H_
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "prlink.h"
|
||||
#include "plarena.h"
|
||||
|
||||
|
||||
/* RC2 operation modes */
|
||||
#define NSS_RC2 0
|
||||
#define NSS_RC2_CBC 1
|
||||
|
||||
/* RC5 operation modes */
|
||||
#define NSS_RC5 0
|
||||
#define NSS_RC5_CBC 1
|
||||
|
||||
/* DES operation modes */
|
||||
#define NSS_DES 0
|
||||
#define NSS_DES_CBC 1
|
||||
#define NSS_DES_EDE3 2
|
||||
#define NSS_DES_EDE3_CBC 3
|
||||
|
||||
#define DES_KEY_LENGTH 8 /* Bytes */
|
||||
|
||||
/* AES operation modes */
|
||||
#define NSS_AES 0
|
||||
#define NSS_AES_CBC 1
|
||||
|
||||
#define DSA_SIGNATURE_LEN 40 /* Bytes */
|
||||
#define DSA_SUBPRIME_LEN 20 /* Bytes */
|
||||
|
||||
/* XXX We shouldn't have to hard code this limit. For
|
||||
* now, this is the quickest way to support ECDSA signature
|
||||
* processing (ECDSA signature lengths depend on curve
|
||||
* size). This limit is sufficient for curves upto
|
||||
* 576 bits.
|
||||
*/
|
||||
#define MAX_ECKEY_LEN 72 /* Bytes */
|
||||
|
||||
/*
|
||||
* Number of bytes each hash algorithm produces
|
||||
*/
|
||||
#define MD2_LENGTH 16 /* Bytes */
|
||||
#define MD5_LENGTH 16 /* Bytes */
|
||||
#define SHA1_LENGTH 20 /* Bytes */
|
||||
#define SHA256_LENGTH 32 /* bytes */
|
||||
#define SHA384_LENGTH 48 /* bytes */
|
||||
#define SHA512_LENGTH 64 /* bytes */
|
||||
#define HASH_LENGTH_MAX SHA512_LENGTH
|
||||
|
||||
/*
|
||||
* Input block size for each hash algorithm.
|
||||
*/
|
||||
|
||||
#define SHA256_BLOCK_LENGTH 64 /* bytes */
|
||||
#define SHA384_BLOCK_LENGTH 128 /* bytes */
|
||||
#define SHA512_BLOCK_LENGTH 128 /* bytes */
|
||||
|
||||
#define AES_KEY_WRAP_IV_BYTES 8
|
||||
#define AES_KEY_WRAP_BLOCK_SIZE 8 /* bytes */
|
||||
#define AES_BLOCK_SIZE 16 /* bytes */
|
||||
|
||||
#define NSS_FREEBL_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
/*
|
||||
* The FIPS 186 algorithm for generating primes P and Q allows only 9
|
||||
* distinct values for the length of P, and only one value for the
|
||||
* length of Q.
|
||||
* The algorithm uses a variable j to indicate which of the 9 lengths
|
||||
* of P is to be used.
|
||||
* The following table relates j to the lengths of P and Q in bits.
|
||||
*
|
||||
* j bits in P bits in Q
|
||||
* _ _________ _________
|
||||
* 0 512 160
|
||||
* 1 576 160
|
||||
* 2 640 160
|
||||
* 3 704 160
|
||||
* 4 768 160
|
||||
* 5 832 160
|
||||
* 6 896 160
|
||||
* 7 960 160
|
||||
* 8 1024 160
|
||||
*
|
||||
* The FIPS-186 compliant PQG generator takes j as an input parameter.
|
||||
*/
|
||||
|
||||
#define DSA_Q_BITS 160
|
||||
#define DSA_MAX_P_BITS 1024
|
||||
#define DSA_MIN_P_BITS 512
|
||||
|
||||
/*
|
||||
* function takes desired number of bits in P,
|
||||
* returns index (0..8) or -1 if number of bits is invalid.
|
||||
*/
|
||||
#define PQG_PBITS_TO_INDEX(bits) ((((bits)-512) % 64) ? -1 : (int)((bits)-512)/64)
|
||||
|
||||
/*
|
||||
* function takes index (0-8)
|
||||
* returns number of bits in P for that index, or -1 if index is invalid.
|
||||
*/
|
||||
#define PQG_INDEX_TO_PBITS(j) (((unsigned)(j) > 8) ? -1 : (512 + 64 * (j)))
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Opaque objects
|
||||
*/
|
||||
|
||||
struct DESContextStr ;
|
||||
struct RC2ContextStr ;
|
||||
struct RC4ContextStr ;
|
||||
struct RC5ContextStr ;
|
||||
struct AESContextStr ;
|
||||
struct MD2ContextStr ;
|
||||
struct MD5ContextStr ;
|
||||
struct SHA1ContextStr ;
|
||||
struct SHA256ContextStr ;
|
||||
struct SHA512ContextStr ;
|
||||
struct AESKeyWrapContextStr ;
|
||||
|
||||
typedef struct DESContextStr DESContext;
|
||||
typedef struct RC2ContextStr RC2Context;
|
||||
typedef struct RC4ContextStr RC4Context;
|
||||
typedef struct RC5ContextStr RC5Context;
|
||||
typedef struct AESContextStr AESContext;
|
||||
typedef struct MD2ContextStr MD2Context;
|
||||
typedef struct MD5ContextStr MD5Context;
|
||||
typedef struct SHA1ContextStr SHA1Context;
|
||||
typedef struct SHA256ContextStr SHA256Context;
|
||||
typedef struct SHA512ContextStr SHA512Context;
|
||||
/* SHA384Context is really a SHA512ContextStr. This is not a mistake. */
|
||||
typedef struct SHA512ContextStr SHA384Context;
|
||||
typedef struct AESKeyWrapContextStr AESKeyWrapContext;
|
||||
|
||||
/***************************************************************************
|
||||
** RSA Public and Private Key structures
|
||||
*/
|
||||
|
||||
/* member names from PKCS#1, section 7.1 */
|
||||
struct RSAPublicKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem modulus;
|
||||
SECItem publicExponent;
|
||||
};
|
||||
typedef struct RSAPublicKeyStr RSAPublicKey;
|
||||
|
||||
/* member names from PKCS#1, section 7.2 */
|
||||
struct RSAPrivateKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem version;
|
||||
SECItem modulus;
|
||||
SECItem publicExponent;
|
||||
SECItem privateExponent;
|
||||
SECItem prime1;
|
||||
SECItem prime2;
|
||||
SECItem exponent1;
|
||||
SECItem exponent2;
|
||||
SECItem coefficient;
|
||||
};
|
||||
typedef struct RSAPrivateKeyStr RSAPrivateKey;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** DSA Public and Private Key and related structures
|
||||
*/
|
||||
|
||||
struct PQGParamsStr {
|
||||
PRArenaPool *arena;
|
||||
SECItem prime; /* p */
|
||||
SECItem subPrime; /* q */
|
||||
SECItem base; /* g */
|
||||
/* XXX chrisk: this needs to be expanded to hold j and validationParms (RFC2459 7.3.2) */
|
||||
};
|
||||
typedef struct PQGParamsStr PQGParams;
|
||||
|
||||
struct PQGVerifyStr {
|
||||
PRArenaPool * arena; /* includes this struct, seed, & h. */
|
||||
unsigned int counter;
|
||||
SECItem seed;
|
||||
SECItem h;
|
||||
};
|
||||
typedef struct PQGVerifyStr PQGVerify;
|
||||
|
||||
struct DSAPublicKeyStr {
|
||||
PQGParams params;
|
||||
SECItem publicValue;
|
||||
};
|
||||
typedef struct DSAPublicKeyStr DSAPublicKey;
|
||||
|
||||
struct DSAPrivateKeyStr {
|
||||
PQGParams params;
|
||||
SECItem publicValue;
|
||||
SECItem privateValue;
|
||||
};
|
||||
typedef struct DSAPrivateKeyStr DSAPrivateKey;
|
||||
|
||||
/***************************************************************************
|
||||
** Diffie-Hellman Public and Private Key and related structures
|
||||
** Structure member names suggested by PKCS#3.
|
||||
*/
|
||||
|
||||
struct DHParamsStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem prime; /* p */
|
||||
SECItem base; /* g */
|
||||
};
|
||||
typedef struct DHParamsStr DHParams;
|
||||
|
||||
struct DHPublicKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem prime;
|
||||
SECItem base;
|
||||
SECItem publicValue;
|
||||
};
|
||||
typedef struct DHPublicKeyStr DHPublicKey;
|
||||
|
||||
struct DHPrivateKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem prime;
|
||||
SECItem base;
|
||||
SECItem publicValue;
|
||||
SECItem privateValue;
|
||||
};
|
||||
typedef struct DHPrivateKeyStr DHPrivateKey;
|
||||
|
||||
/***************************************************************************
|
||||
** Data structures used for elliptic curve parameters and
|
||||
** public and private keys.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The ECParams data structures can encode elliptic curve
|
||||
** parameters for both GFp and GF2m curves.
|
||||
*/
|
||||
|
||||
typedef enum { ec_params_explicit,
|
||||
ec_params_named
|
||||
} ECParamsType;
|
||||
|
||||
typedef enum { ec_field_GFp = 1,
|
||||
ec_field_GF2m
|
||||
} ECFieldType;
|
||||
|
||||
struct ECFieldIDStr {
|
||||
int size; /* field size in bits */
|
||||
ECFieldType type;
|
||||
union {
|
||||
SECItem prime; /* prime p for (GFp) */
|
||||
SECItem poly; /* irreducible binary polynomial for (GF2m) */
|
||||
} u;
|
||||
int k1; /* first coefficient of pentanomial or
|
||||
* the only coefficient of trinomial
|
||||
*/
|
||||
int k2; /* two remaining coefficients of pentanomial */
|
||||
int k3;
|
||||
};
|
||||
typedef struct ECFieldIDStr ECFieldID;
|
||||
|
||||
struct ECCurveStr {
|
||||
SECItem a; /* contains octet stream encoding of
|
||||
* field element (X9.62 section 4.3.3)
|
||||
*/
|
||||
SECItem b;
|
||||
SECItem seed;
|
||||
};
|
||||
typedef struct ECCurveStr ECCurve;
|
||||
|
||||
struct ECParamsStr {
|
||||
PRArenaPool * arena;
|
||||
ECParamsType type;
|
||||
ECFieldID fieldID;
|
||||
ECCurve curve;
|
||||
SECItem base;
|
||||
SECItem order;
|
||||
int cofactor;
|
||||
SECItem DEREncoding;
|
||||
};
|
||||
typedef struct ECParamsStr ECParams;
|
||||
|
||||
struct ECPublicKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* elliptic curve point encoded as
|
||||
* octet stream.
|
||||
*/
|
||||
};
|
||||
typedef struct ECPublicKeyStr ECPublicKey;
|
||||
|
||||
struct ECPrivateKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* encoded ec point */
|
||||
SECItem privateValue; /* private big integer */
|
||||
};
|
||||
typedef struct ECPrivateKeyStr ECPrivateKey;
|
||||
|
||||
#endif /* _BLAPIT_H_ */
|
||||
@@ -1,103 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
# only do this in the outermost freebl build.
|
||||
ifndef FREEBL_RECURSIVE_BUILD
|
||||
# we only do this stuff for some of the 32-bit builds, no 64-bit builds
|
||||
ifndef USE_64
|
||||
|
||||
ifeq ($(OS_TARGET), HP-UX)
|
||||
ifneq ($(OS_TEST), ia64)
|
||||
FREEBL_EXTENDED_BUILD = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),SunOS)
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
FREEBL_EXTENDED_BUILD = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef FREEBL_EXTENDED_BUILD
|
||||
# We're going to change this build so that it builds libfreebl.a with
|
||||
# just loader.c. Then we have to build this directory twice again to
|
||||
# build the two DSOs.
|
||||
# To build libfreebl.a with just loader.c, we must now override many
|
||||
# of the make variables setup by the prior inclusion of CORECONF's config.mk
|
||||
|
||||
CSRCS = loader.c sysrand.c
|
||||
SIMPLE_OBJS = $(CSRCS:.c=$(OBJ_SUFFIX))
|
||||
OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(SIMPLE_OBJS))
|
||||
ALL_TRASH := $(TARGETS) $(OBJS) $(OBJDIR) LOGS TAGS $(GARBAGE) \
|
||||
$(NOSUCHFILE) so_locations
|
||||
endif
|
||||
|
||||
#end of 32-bit only stuff.
|
||||
endif
|
||||
|
||||
# Override the values defined in coreconf's ruleset.mk.
|
||||
#
|
||||
# - (1) LIBRARY: a static (archival) library
|
||||
# - (2) SHARED_LIBRARY: a shared (dynamic link) library
|
||||
# - (3) IMPORT_LIBRARY: an import library, used only on Windows
|
||||
# - (4) PROGRAM: an executable binary
|
||||
#
|
||||
# override these variables to prevent building a DSO/DLL.
|
||||
TARGETS = $(LIBRARY)
|
||||
SHARED_LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
else
|
||||
# This is a recursive build.
|
||||
|
||||
TARGETS = $(SHARED_LIBRARY)
|
||||
LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
#ifeq ($(OS_TARGET), HP-UX)
|
||||
EXTRA_LIBS += \
|
||||
$(DIST)/lib/libsecutil.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
|
||||
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(DIST)/lib/ \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
-lc
|
||||
#endif
|
||||
|
||||
endif
|
||||
@@ -1,683 +0,0 @@
|
||||
/*
|
||||
* des.c
|
||||
*
|
||||
* core source file for DES-150 library
|
||||
* Make key schedule from DES key.
|
||||
* Encrypt/Decrypt one 8-byte block.
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Nelson B. Bolyard,
|
||||
* nelsonb@iname.com. Portions created by Nelson B. Bolyard are
|
||||
* Copyright (C) 1990, 2000 Nelson B. Bolyard, All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
#include "des.h"
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
/* #define USE_INDEXING 1 */
|
||||
|
||||
/*
|
||||
* The tables below are the 8 sbox functions, with the 6-bit input permutation
|
||||
* and the 32-bit output permutation pre-computed.
|
||||
* They are shifted circularly to the left 3 bits, which removes 2 shifts
|
||||
* and an or from each round by reducing the number of sboxes whose
|
||||
* indices cross word broundaries from 2 to 1.
|
||||
*/
|
||||
|
||||
static const HALF SP[8][64] = {
|
||||
/* Box S1 */ {
|
||||
0x04041000, 0x00000000, 0x00040000, 0x04041010,
|
||||
0x04040010, 0x00041010, 0x00000010, 0x00040000,
|
||||
0x00001000, 0x04041000, 0x04041010, 0x00001000,
|
||||
0x04001010, 0x04040010, 0x04000000, 0x00000010,
|
||||
0x00001010, 0x04001000, 0x04001000, 0x00041000,
|
||||
0x00041000, 0x04040000, 0x04040000, 0x04001010,
|
||||
0x00040010, 0x04000010, 0x04000010, 0x00040010,
|
||||
0x00000000, 0x00001010, 0x00041010, 0x04000000,
|
||||
0x00040000, 0x04041010, 0x00000010, 0x04040000,
|
||||
0x04041000, 0x04000000, 0x04000000, 0x00001000,
|
||||
0x04040010, 0x00040000, 0x00041000, 0x04000010,
|
||||
0x00001000, 0x00000010, 0x04001010, 0x00041010,
|
||||
0x04041010, 0x00040010, 0x04040000, 0x04001010,
|
||||
0x04000010, 0x00001010, 0x00041010, 0x04041000,
|
||||
0x00001010, 0x04001000, 0x04001000, 0x00000000,
|
||||
0x00040010, 0x00041000, 0x00000000, 0x04040010
|
||||
},
|
||||
/* Box S2 */ {
|
||||
0x00420082, 0x00020002, 0x00020000, 0x00420080,
|
||||
0x00400000, 0x00000080, 0x00400082, 0x00020082,
|
||||
0x00000082, 0x00420082, 0x00420002, 0x00000002,
|
||||
0x00020002, 0x00400000, 0x00000080, 0x00400082,
|
||||
0x00420000, 0x00400080, 0x00020082, 0x00000000,
|
||||
0x00000002, 0x00020000, 0x00420080, 0x00400002,
|
||||
0x00400080, 0x00000082, 0x00000000, 0x00420000,
|
||||
0x00020080, 0x00420002, 0x00400002, 0x00020080,
|
||||
0x00000000, 0x00420080, 0x00400082, 0x00400000,
|
||||
0x00020082, 0x00400002, 0x00420002, 0x00020000,
|
||||
0x00400002, 0x00020002, 0x00000080, 0x00420082,
|
||||
0x00420080, 0x00000080, 0x00020000, 0x00000002,
|
||||
0x00020080, 0x00420002, 0x00400000, 0x00000082,
|
||||
0x00400080, 0x00020082, 0x00000082, 0x00400080,
|
||||
0x00420000, 0x00000000, 0x00020002, 0x00020080,
|
||||
0x00000002, 0x00400082, 0x00420082, 0x00420000
|
||||
},
|
||||
/* Box S3 */ {
|
||||
0x00000820, 0x20080800, 0x00000000, 0x20080020,
|
||||
0x20000800, 0x00000000, 0x00080820, 0x20000800,
|
||||
0x00080020, 0x20000020, 0x20000020, 0x00080000,
|
||||
0x20080820, 0x00080020, 0x20080000, 0x00000820,
|
||||
0x20000000, 0x00000020, 0x20080800, 0x00000800,
|
||||
0x00080800, 0x20080000, 0x20080020, 0x00080820,
|
||||
0x20000820, 0x00080800, 0x00080000, 0x20000820,
|
||||
0x00000020, 0x20080820, 0x00000800, 0x20000000,
|
||||
0x20080800, 0x20000000, 0x00080020, 0x00000820,
|
||||
0x00080000, 0x20080800, 0x20000800, 0x00000000,
|
||||
0x00000800, 0x00080020, 0x20080820, 0x20000800,
|
||||
0x20000020, 0x00000800, 0x00000000, 0x20080020,
|
||||
0x20000820, 0x00080000, 0x20000000, 0x20080820,
|
||||
0x00000020, 0x00080820, 0x00080800, 0x20000020,
|
||||
0x20080000, 0x20000820, 0x00000820, 0x20080000,
|
||||
0x00080820, 0x00000020, 0x20080020, 0x00080800
|
||||
},
|
||||
/* Box S4 */ {
|
||||
0x02008004, 0x00008204, 0x00008204, 0x00000200,
|
||||
0x02008200, 0x02000204, 0x02000004, 0x00008004,
|
||||
0x00000000, 0x02008000, 0x02008000, 0x02008204,
|
||||
0x00000204, 0x00000000, 0x02000200, 0x02000004,
|
||||
0x00000004, 0x00008000, 0x02000000, 0x02008004,
|
||||
0x00000200, 0x02000000, 0x00008004, 0x00008200,
|
||||
0x02000204, 0x00000004, 0x00008200, 0x02000200,
|
||||
0x00008000, 0x02008200, 0x02008204, 0x00000204,
|
||||
0x02000200, 0x02000004, 0x02008000, 0x02008204,
|
||||
0x00000204, 0x00000000, 0x00000000, 0x02008000,
|
||||
0x00008200, 0x02000200, 0x02000204, 0x00000004,
|
||||
0x02008004, 0x00008204, 0x00008204, 0x00000200,
|
||||
0x02008204, 0x00000204, 0x00000004, 0x00008000,
|
||||
0x02000004, 0x00008004, 0x02008200, 0x02000204,
|
||||
0x00008004, 0x00008200, 0x02000000, 0x02008004,
|
||||
0x00000200, 0x02000000, 0x00008000, 0x02008200
|
||||
},
|
||||
/* Box S5 */ {
|
||||
0x00000400, 0x08200400, 0x08200000, 0x08000401,
|
||||
0x00200000, 0x00000400, 0x00000001, 0x08200000,
|
||||
0x00200401, 0x00200000, 0x08000400, 0x00200401,
|
||||
0x08000401, 0x08200001, 0x00200400, 0x00000001,
|
||||
0x08000000, 0x00200001, 0x00200001, 0x00000000,
|
||||
0x00000401, 0x08200401, 0x08200401, 0x08000400,
|
||||
0x08200001, 0x00000401, 0x00000000, 0x08000001,
|
||||
0x08200400, 0x08000000, 0x08000001, 0x00200400,
|
||||
0x00200000, 0x08000401, 0x00000400, 0x08000000,
|
||||
0x00000001, 0x08200000, 0x08000401, 0x00200401,
|
||||
0x08000400, 0x00000001, 0x08200001, 0x08200400,
|
||||
0x00200401, 0x00000400, 0x08000000, 0x08200001,
|
||||
0x08200401, 0x00200400, 0x08000001, 0x08200401,
|
||||
0x08200000, 0x00000000, 0x00200001, 0x08000001,
|
||||
0x00200400, 0x08000400, 0x00000401, 0x00200000,
|
||||
0x00000000, 0x00200001, 0x08200400, 0x00000401
|
||||
},
|
||||
/* Box S6 */ {
|
||||
0x80000040, 0x81000000, 0x00010000, 0x81010040,
|
||||
0x81000000, 0x00000040, 0x81010040, 0x01000000,
|
||||
0x80010000, 0x01010040, 0x01000000, 0x80000040,
|
||||
0x01000040, 0x80010000, 0x80000000, 0x00010040,
|
||||
0x00000000, 0x01000040, 0x80010040, 0x00010000,
|
||||
0x01010000, 0x80010040, 0x00000040, 0x81000040,
|
||||
0x81000040, 0x00000000, 0x01010040, 0x81010000,
|
||||
0x00010040, 0x01010000, 0x81010000, 0x80000000,
|
||||
0x80010000, 0x00000040, 0x81000040, 0x01010000,
|
||||
0x81010040, 0x01000000, 0x00010040, 0x80000040,
|
||||
0x01000000, 0x80010000, 0x80000000, 0x00010040,
|
||||
0x80000040, 0x81010040, 0x01010000, 0x81000000,
|
||||
0x01010040, 0x81010000, 0x00000000, 0x81000040,
|
||||
0x00000040, 0x00010000, 0x81000000, 0x01010040,
|
||||
0x00010000, 0x01000040, 0x80010040, 0x00000000,
|
||||
0x81010000, 0x80000000, 0x01000040, 0x80010040
|
||||
},
|
||||
/* Box S7 */ {
|
||||
0x00800000, 0x10800008, 0x10002008, 0x00000000,
|
||||
0x00002000, 0x10002008, 0x00802008, 0x10802000,
|
||||
0x10802008, 0x00800000, 0x00000000, 0x10000008,
|
||||
0x00000008, 0x10000000, 0x10800008, 0x00002008,
|
||||
0x10002000, 0x00802008, 0x00800008, 0x10002000,
|
||||
0x10000008, 0x10800000, 0x10802000, 0x00800008,
|
||||
0x10800000, 0x00002000, 0x00002008, 0x10802008,
|
||||
0x00802000, 0x00000008, 0x10000000, 0x00802000,
|
||||
0x10000000, 0x00802000, 0x00800000, 0x10002008,
|
||||
0x10002008, 0x10800008, 0x10800008, 0x00000008,
|
||||
0x00800008, 0x10000000, 0x10002000, 0x00800000,
|
||||
0x10802000, 0x00002008, 0x00802008, 0x10802000,
|
||||
0x00002008, 0x10000008, 0x10802008, 0x10800000,
|
||||
0x00802000, 0x00000000, 0x00000008, 0x10802008,
|
||||
0x00000000, 0x00802008, 0x10800000, 0x00002000,
|
||||
0x10000008, 0x10002000, 0x00002000, 0x00800008
|
||||
},
|
||||
/* Box S8 */ {
|
||||
0x40004100, 0x00004000, 0x00100000, 0x40104100,
|
||||
0x40000000, 0x40004100, 0x00000100, 0x40000000,
|
||||
0x00100100, 0x40100000, 0x40104100, 0x00104000,
|
||||
0x40104000, 0x00104100, 0x00004000, 0x00000100,
|
||||
0x40100000, 0x40000100, 0x40004000, 0x00004100,
|
||||
0x00104000, 0x00100100, 0x40100100, 0x40104000,
|
||||
0x00004100, 0x00000000, 0x00000000, 0x40100100,
|
||||
0x40000100, 0x40004000, 0x00104100, 0x00100000,
|
||||
0x00104100, 0x00100000, 0x40104000, 0x00004000,
|
||||
0x00000100, 0x40100100, 0x00004000, 0x00104100,
|
||||
0x40004000, 0x00000100, 0x40000100, 0x40100000,
|
||||
0x40100100, 0x40000000, 0x00100000, 0x40004100,
|
||||
0x00000000, 0x40104100, 0x00100100, 0x40000100,
|
||||
0x40100000, 0x40004000, 0x40004100, 0x00000000,
|
||||
0x40104100, 0x00104000, 0x00104000, 0x00004100,
|
||||
0x00004100, 0x00100100, 0x40000000, 0x40104000
|
||||
}
|
||||
};
|
||||
|
||||
static const HALF PC2[8][64] = {
|
||||
/* table 0 */ {
|
||||
0x00000000, 0x00001000, 0x04000000, 0x04001000,
|
||||
0x00100000, 0x00101000, 0x04100000, 0x04101000,
|
||||
0x00008000, 0x00009000, 0x04008000, 0x04009000,
|
||||
0x00108000, 0x00109000, 0x04108000, 0x04109000,
|
||||
0x00000004, 0x00001004, 0x04000004, 0x04001004,
|
||||
0x00100004, 0x00101004, 0x04100004, 0x04101004,
|
||||
0x00008004, 0x00009004, 0x04008004, 0x04009004,
|
||||
0x00108004, 0x00109004, 0x04108004, 0x04109004,
|
||||
0x08000000, 0x08001000, 0x0c000000, 0x0c001000,
|
||||
0x08100000, 0x08101000, 0x0c100000, 0x0c101000,
|
||||
0x08008000, 0x08009000, 0x0c008000, 0x0c009000,
|
||||
0x08108000, 0x08109000, 0x0c108000, 0x0c109000,
|
||||
0x08000004, 0x08001004, 0x0c000004, 0x0c001004,
|
||||
0x08100004, 0x08101004, 0x0c100004, 0x0c101004,
|
||||
0x08008004, 0x08009004, 0x0c008004, 0x0c009004,
|
||||
0x08108004, 0x08109004, 0x0c108004, 0x0c109004
|
||||
},
|
||||
/* table 1 */ {
|
||||
0x00000000, 0x00002000, 0x80000000, 0x80002000,
|
||||
0x00000008, 0x00002008, 0x80000008, 0x80002008,
|
||||
0x00200000, 0x00202000, 0x80200000, 0x80202000,
|
||||
0x00200008, 0x00202008, 0x80200008, 0x80202008,
|
||||
0x20000000, 0x20002000, 0xa0000000, 0xa0002000,
|
||||
0x20000008, 0x20002008, 0xa0000008, 0xa0002008,
|
||||
0x20200000, 0x20202000, 0xa0200000, 0xa0202000,
|
||||
0x20200008, 0x20202008, 0xa0200008, 0xa0202008,
|
||||
0x00000400, 0x00002400, 0x80000400, 0x80002400,
|
||||
0x00000408, 0x00002408, 0x80000408, 0x80002408,
|
||||
0x00200400, 0x00202400, 0x80200400, 0x80202400,
|
||||
0x00200408, 0x00202408, 0x80200408, 0x80202408,
|
||||
0x20000400, 0x20002400, 0xa0000400, 0xa0002400,
|
||||
0x20000408, 0x20002408, 0xa0000408, 0xa0002408,
|
||||
0x20200400, 0x20202400, 0xa0200400, 0xa0202400,
|
||||
0x20200408, 0x20202408, 0xa0200408, 0xa0202408
|
||||
},
|
||||
/* table 2 */ {
|
||||
0x00000000, 0x00004000, 0x00000020, 0x00004020,
|
||||
0x00080000, 0x00084000, 0x00080020, 0x00084020,
|
||||
0x00000800, 0x00004800, 0x00000820, 0x00004820,
|
||||
0x00080800, 0x00084800, 0x00080820, 0x00084820,
|
||||
0x00000010, 0x00004010, 0x00000030, 0x00004030,
|
||||
0x00080010, 0x00084010, 0x00080030, 0x00084030,
|
||||
0x00000810, 0x00004810, 0x00000830, 0x00004830,
|
||||
0x00080810, 0x00084810, 0x00080830, 0x00084830,
|
||||
0x00400000, 0x00404000, 0x00400020, 0x00404020,
|
||||
0x00480000, 0x00484000, 0x00480020, 0x00484020,
|
||||
0x00400800, 0x00404800, 0x00400820, 0x00404820,
|
||||
0x00480800, 0x00484800, 0x00480820, 0x00484820,
|
||||
0x00400010, 0x00404010, 0x00400030, 0x00404030,
|
||||
0x00480010, 0x00484010, 0x00480030, 0x00484030,
|
||||
0x00400810, 0x00404810, 0x00400830, 0x00404830,
|
||||
0x00480810, 0x00484810, 0x00480830, 0x00484830
|
||||
},
|
||||
/* table 3 */ {
|
||||
0x00000000, 0x40000000, 0x00000080, 0x40000080,
|
||||
0x00040000, 0x40040000, 0x00040080, 0x40040080,
|
||||
0x00000040, 0x40000040, 0x000000c0, 0x400000c0,
|
||||
0x00040040, 0x40040040, 0x000400c0, 0x400400c0,
|
||||
0x10000000, 0x50000000, 0x10000080, 0x50000080,
|
||||
0x10040000, 0x50040000, 0x10040080, 0x50040080,
|
||||
0x10000040, 0x50000040, 0x100000c0, 0x500000c0,
|
||||
0x10040040, 0x50040040, 0x100400c0, 0x500400c0,
|
||||
0x00800000, 0x40800000, 0x00800080, 0x40800080,
|
||||
0x00840000, 0x40840000, 0x00840080, 0x40840080,
|
||||
0x00800040, 0x40800040, 0x008000c0, 0x408000c0,
|
||||
0x00840040, 0x40840040, 0x008400c0, 0x408400c0,
|
||||
0x10800000, 0x50800000, 0x10800080, 0x50800080,
|
||||
0x10840000, 0x50840000, 0x10840080, 0x50840080,
|
||||
0x10800040, 0x50800040, 0x108000c0, 0x508000c0,
|
||||
0x10840040, 0x50840040, 0x108400c0, 0x508400c0
|
||||
},
|
||||
/* table 4 */ {
|
||||
0x00000000, 0x00000008, 0x08000000, 0x08000008,
|
||||
0x00040000, 0x00040008, 0x08040000, 0x08040008,
|
||||
0x00002000, 0x00002008, 0x08002000, 0x08002008,
|
||||
0x00042000, 0x00042008, 0x08042000, 0x08042008,
|
||||
0x80000000, 0x80000008, 0x88000000, 0x88000008,
|
||||
0x80040000, 0x80040008, 0x88040000, 0x88040008,
|
||||
0x80002000, 0x80002008, 0x88002000, 0x88002008,
|
||||
0x80042000, 0x80042008, 0x88042000, 0x88042008,
|
||||
0x00080000, 0x00080008, 0x08080000, 0x08080008,
|
||||
0x000c0000, 0x000c0008, 0x080c0000, 0x080c0008,
|
||||
0x00082000, 0x00082008, 0x08082000, 0x08082008,
|
||||
0x000c2000, 0x000c2008, 0x080c2000, 0x080c2008,
|
||||
0x80080000, 0x80080008, 0x88080000, 0x88080008,
|
||||
0x800c0000, 0x800c0008, 0x880c0000, 0x880c0008,
|
||||
0x80082000, 0x80082008, 0x88082000, 0x88082008,
|
||||
0x800c2000, 0x800c2008, 0x880c2000, 0x880c2008
|
||||
},
|
||||
/* table 5 */ {
|
||||
0x00000000, 0x00400000, 0x00008000, 0x00408000,
|
||||
0x40000000, 0x40400000, 0x40008000, 0x40408000,
|
||||
0x00000020, 0x00400020, 0x00008020, 0x00408020,
|
||||
0x40000020, 0x40400020, 0x40008020, 0x40408020,
|
||||
0x00001000, 0x00401000, 0x00009000, 0x00409000,
|
||||
0x40001000, 0x40401000, 0x40009000, 0x40409000,
|
||||
0x00001020, 0x00401020, 0x00009020, 0x00409020,
|
||||
0x40001020, 0x40401020, 0x40009020, 0x40409020,
|
||||
0x00100000, 0x00500000, 0x00108000, 0x00508000,
|
||||
0x40100000, 0x40500000, 0x40108000, 0x40508000,
|
||||
0x00100020, 0x00500020, 0x00108020, 0x00508020,
|
||||
0x40100020, 0x40500020, 0x40108020, 0x40508020,
|
||||
0x00101000, 0x00501000, 0x00109000, 0x00509000,
|
||||
0x40101000, 0x40501000, 0x40109000, 0x40509000,
|
||||
0x00101020, 0x00501020, 0x00109020, 0x00509020,
|
||||
0x40101020, 0x40501020, 0x40109020, 0x40509020
|
||||
},
|
||||
/* table 6 */ {
|
||||
0x00000000, 0x00000040, 0x04000000, 0x04000040,
|
||||
0x00000800, 0x00000840, 0x04000800, 0x04000840,
|
||||
0x00800000, 0x00800040, 0x04800000, 0x04800040,
|
||||
0x00800800, 0x00800840, 0x04800800, 0x04800840,
|
||||
0x10000000, 0x10000040, 0x14000000, 0x14000040,
|
||||
0x10000800, 0x10000840, 0x14000800, 0x14000840,
|
||||
0x10800000, 0x10800040, 0x14800000, 0x14800040,
|
||||
0x10800800, 0x10800840, 0x14800800, 0x14800840,
|
||||
0x00000080, 0x000000c0, 0x04000080, 0x040000c0,
|
||||
0x00000880, 0x000008c0, 0x04000880, 0x040008c0,
|
||||
0x00800080, 0x008000c0, 0x04800080, 0x048000c0,
|
||||
0x00800880, 0x008008c0, 0x04800880, 0x048008c0,
|
||||
0x10000080, 0x100000c0, 0x14000080, 0x140000c0,
|
||||
0x10000880, 0x100008c0, 0x14000880, 0x140008c0,
|
||||
0x10800080, 0x108000c0, 0x14800080, 0x148000c0,
|
||||
0x10800880, 0x108008c0, 0x14800880, 0x148008c0
|
||||
},
|
||||
/* table 7 */ {
|
||||
0x00000000, 0x00000010, 0x00000400, 0x00000410,
|
||||
0x00000004, 0x00000014, 0x00000404, 0x00000414,
|
||||
0x00004000, 0x00004010, 0x00004400, 0x00004410,
|
||||
0x00004004, 0x00004014, 0x00004404, 0x00004414,
|
||||
0x20000000, 0x20000010, 0x20000400, 0x20000410,
|
||||
0x20000004, 0x20000014, 0x20000404, 0x20000414,
|
||||
0x20004000, 0x20004010, 0x20004400, 0x20004410,
|
||||
0x20004004, 0x20004014, 0x20004404, 0x20004414,
|
||||
0x00200000, 0x00200010, 0x00200400, 0x00200410,
|
||||
0x00200004, 0x00200014, 0x00200404, 0x00200414,
|
||||
0x00204000, 0x00204010, 0x00204400, 0x00204410,
|
||||
0x00204004, 0x00204014, 0x00204404, 0x00204414,
|
||||
0x20200000, 0x20200010, 0x20200400, 0x20200410,
|
||||
0x20200004, 0x20200014, 0x20200404, 0x20200414,
|
||||
0x20204000, 0x20204010, 0x20204400, 0x20204410,
|
||||
0x20204004, 0x20204014, 0x20204404, 0x20204414
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The PC-1 Permutation
|
||||
* If we number the bits of the 8 bytes of key input like this (in octal):
|
||||
* 00 01 02 03 04 05 06 07
|
||||
* 10 11 12 13 14 15 16 17
|
||||
* 20 21 22 23 24 25 26 27
|
||||
* 30 31 32 33 34 35 36 37
|
||||
* 40 41 42 43 44 45 46 47
|
||||
* 50 51 52 53 54 55 56 57
|
||||
* 60 61 62 63 64 65 66 67
|
||||
* 70 71 72 73 74 75 76 77
|
||||
* then after the PC-1 permutation,
|
||||
* C0 is
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 73 63 53 43
|
||||
* D0 is
|
||||
* 76 66 56 46 36 26 16 06
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* 33 23 13 03
|
||||
* and these parity bits have been discarded:
|
||||
* 77 67 57 47 37 27 17 07
|
||||
*
|
||||
* We achieve this by flipping the input matrix about the diagonal from 70-07,
|
||||
* getting left =
|
||||
* 77 67 57 47 37 27 17 07 (these are the parity bits)
|
||||
* 76 66 56 46 36 26 16 06
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* right =
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* then byte swap right, ala htonl() on a little endian machine.
|
||||
* right =
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 71 67 57 47 37 27 11 07
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* then
|
||||
* c0 = right >> 4;
|
||||
* d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
|
||||
*/
|
||||
|
||||
#define FLIP_RIGHT_DIAGONAL(word, temp) \
|
||||
temp = (word ^ (word >> 18)) & 0x00003333; \
|
||||
word ^= temp | (temp << 18); \
|
||||
temp = (word ^ (word >> 9)) & 0x00550055; \
|
||||
word ^= temp | (temp << 9);
|
||||
|
||||
#define BYTESWAP(word, temp) \
|
||||
word = (word >> 16) | (word << 16); \
|
||||
temp = 0x00ff00ff; \
|
||||
word = ((word & temp) << 8) | ((word >> 8) & temp);
|
||||
|
||||
#define PC1(left, right, c0, d0, temp) \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4; \
|
||||
FLIP_RIGHT_DIAGONAL(left, temp); \
|
||||
FLIP_RIGHT_DIAGONAL(right, temp); \
|
||||
BYTESWAP(right, temp); \
|
||||
c0 = right >> 4; \
|
||||
d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
|
||||
|
||||
#define LEFT_SHIFT_1( reg ) (((reg << 1) | (reg >> 27)) & 0x0FFFFFFF)
|
||||
#define LEFT_SHIFT_2( reg ) (((reg << 2) | (reg >> 26)) & 0x0FFFFFFF)
|
||||
|
||||
/*
|
||||
* setup key schedules from key
|
||||
*/
|
||||
|
||||
void
|
||||
DES_MakeSchedule( HALF * ks, const BYTE * key, DESDirection direction)
|
||||
{
|
||||
register HALF left, right;
|
||||
register HALF c0, d0;
|
||||
register HALF temp;
|
||||
int delta;
|
||||
unsigned int ls;
|
||||
|
||||
#if defined(_X86_)
|
||||
left = HALFPTR(key)[0];
|
||||
right = HALFPTR(key)[1];
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#else
|
||||
if (((ptrdiff_t)key & 0x03) == 0) {
|
||||
left = HALFPTR(key)[0];
|
||||
right = HALFPTR(key)[1];
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
} else {
|
||||
left = ((HALF)key[0] << 24) | ((HALF)key[1] << 16) |
|
||||
((HALF)key[2] << 8) | key[3];
|
||||
right = ((HALF)key[4] << 24) | ((HALF)key[5] << 16) |
|
||||
((HALF)key[6] << 8) | key[7];
|
||||
}
|
||||
#endif
|
||||
|
||||
PC1(left, right, c0, d0, temp);
|
||||
|
||||
if (direction == DES_ENCRYPT) {
|
||||
delta = 2 * (int)sizeof(HALF);
|
||||
} else {
|
||||
ks += 30;
|
||||
delta = (-2) * (int)sizeof(HALF);
|
||||
}
|
||||
|
||||
for (ls = 0x8103; ls; ls >>= 1) {
|
||||
if ( ls & 1 ) {
|
||||
c0 = LEFT_SHIFT_1( c0 );
|
||||
d0 = LEFT_SHIFT_1( d0 );
|
||||
} else {
|
||||
c0 = LEFT_SHIFT_2( c0 );
|
||||
d0 = LEFT_SHIFT_2( d0 );
|
||||
}
|
||||
|
||||
#ifdef USE_INDEXING
|
||||
#define PC2LOOKUP(b,c) PC2[b][c]
|
||||
|
||||
left = PC2LOOKUP(0, ((c0 >> 22) & 0x3F) );
|
||||
left |= PC2LOOKUP(1, ((c0 >> 13) & 0x3F) );
|
||||
left |= PC2LOOKUP(2, ((c0 >> 4) & 0x38) | (c0 & 0x7) );
|
||||
left |= PC2LOOKUP(3, ((c0>>18)&0xC) | ((c0>>11)&0x3) | (c0&0x30));
|
||||
|
||||
right = PC2LOOKUP(4, ((d0 >> 22) & 0x3F) );
|
||||
right |= PC2LOOKUP(5, ((d0 >> 15) & 0x30) | ((d0 >> 14) & 0xf) );
|
||||
right |= PC2LOOKUP(6, ((d0 >> 7) & 0x3F) );
|
||||
right |= PC2LOOKUP(7, ((d0 >> 1) & 0x3C) | (d0 & 0x3));
|
||||
#else
|
||||
#define PC2LOOKUP(b,c) *(HALF *)((BYTE *)&PC2[b][0]+(c))
|
||||
|
||||
left = PC2LOOKUP(0, ((c0 >> 20) & 0xFC) );
|
||||
left |= PC2LOOKUP(1, ((c0 >> 11) & 0xFC) );
|
||||
left |= PC2LOOKUP(2, ((c0 >> 2) & 0xE0) | ((c0 << 2) & 0x1C) );
|
||||
left |= PC2LOOKUP(3, ((c0>>16)&0x30)|((c0>>9)&0xC)|((c0<<2)&0xC0));
|
||||
|
||||
right = PC2LOOKUP(4, ((d0 >> 20) & 0xFC) );
|
||||
right |= PC2LOOKUP(5, ((d0 >> 13) & 0xC0) | ((d0 >> 12) & 0x3C) );
|
||||
right |= PC2LOOKUP(6, ((d0 >> 5) & 0xFC) );
|
||||
right |= PC2LOOKUP(7, ((d0 << 1) & 0xF0) | ((d0 << 2) & 0x0C));
|
||||
#endif
|
||||
/* left contains key bits for S1 S3 S2 S4 */
|
||||
/* right contains key bits for S6 S8 S5 S7 */
|
||||
temp = (left << 16) /* S2 S4 XX XX */
|
||||
| (right >> 16); /* XX XX S6 S8 */
|
||||
ks[0] = temp;
|
||||
|
||||
temp = (left & 0xffff0000) /* S1 S3 XX XX */
|
||||
| (right & 0x0000ffff);/* XX XX S5 S7 */
|
||||
ks[1] = temp;
|
||||
|
||||
ks = (HALF*)((BYTE *)ks + delta);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The DES Initial Permutation
|
||||
* if we number the bits of the 8 bytes of input like this (in octal):
|
||||
* 00 01 02 03 04 05 06 07
|
||||
* 10 11 12 13 14 15 16 17
|
||||
* 20 21 22 23 24 25 26 27
|
||||
* 30 31 32 33 34 35 36 37
|
||||
* 40 41 42 43 44 45 46 47
|
||||
* 50 51 52 53 54 55 56 57
|
||||
* 60 61 62 63 64 65 66 67
|
||||
* 70 71 72 73 74 75 76 77
|
||||
* then after the initial permutation, they will be in this order.
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 77 67 57 47 37 27 17 07
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* 76 66 56 46 36 26 16 06
|
||||
*
|
||||
* One way to do this is in two steps:
|
||||
* 1. Flip this matrix about the diagonal from 70-07 as done for PC1.
|
||||
* 2. Rearrange the bytes (rows in the matrix above) with the following code.
|
||||
*
|
||||
* #define swapHiLo(word, temp) \
|
||||
* temp = (word ^ (word >> 24)) & 0x000000ff; \
|
||||
* word ^= temp | (temp << 24);
|
||||
*
|
||||
* right ^= temp = ((left << 8) ^ right) & 0xff00ff00;
|
||||
* left ^= temp >> 8;
|
||||
* swapHiLo(left, temp);
|
||||
* swapHiLo(right,temp);
|
||||
*
|
||||
* However, the two steps can be combined, so that the rows are rearranged
|
||||
* while the matrix is being flipped, reducing the number of bit exchange
|
||||
* operations from 8 ot 5.
|
||||
*
|
||||
* Initial Permutation */
|
||||
#define IP(left, right, temp) \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4; \
|
||||
right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
|
||||
left ^= temp << 16; \
|
||||
right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
|
||||
left ^= temp >> 2; \
|
||||
right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
|
||||
left ^= temp >> 8; \
|
||||
right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
|
||||
left ^= temp << 1;
|
||||
|
||||
/* The Final (Inverse Initial) permutation is done by reversing the
|
||||
** steps of the Initital Permutation
|
||||
*/
|
||||
|
||||
#define FP(left, right, temp) \
|
||||
right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
|
||||
left ^= temp << 1; \
|
||||
right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
|
||||
left ^= temp >> 8; \
|
||||
right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
|
||||
left ^= temp >> 2; \
|
||||
right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
|
||||
left ^= temp << 16; \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4;
|
||||
|
||||
void
|
||||
DES_Do1Block(HALF * ks, const BYTE * inbuf, BYTE * outbuf)
|
||||
{
|
||||
register HALF left, right;
|
||||
register HALF temp;
|
||||
|
||||
#if defined(_X86_)
|
||||
left = HALFPTR(inbuf)[0];
|
||||
right = HALFPTR(inbuf)[1];
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#else
|
||||
if (((ptrdiff_t)inbuf & 0x03) == 0) {
|
||||
left = HALFPTR(inbuf)[0];
|
||||
right = HALFPTR(inbuf)[1];
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
} else {
|
||||
left = ((HALF)inbuf[0] << 24) | ((HALF)inbuf[1] << 16) |
|
||||
((HALF)inbuf[2] << 8) | inbuf[3];
|
||||
right = ((HALF)inbuf[4] << 24) | ((HALF)inbuf[5] << 16) |
|
||||
((HALF)inbuf[6] << 8) | inbuf[7];
|
||||
}
|
||||
#endif
|
||||
|
||||
IP(left, right, temp);
|
||||
|
||||
/* shift the values left circularly 3 bits. */
|
||||
left = (left << 3) | (left >> 29);
|
||||
right = (right << 3) | (right >> 29);
|
||||
|
||||
#ifdef USE_INDEXING
|
||||
#define KSLOOKUP(s,b) SP[s][((temp >> (b+2)) & 0x3f)]
|
||||
#else
|
||||
#define KSLOOKUP(s,b) *(HALF*)((BYTE*)&SP[s][0]+((temp >> b) & 0xFC))
|
||||
#endif
|
||||
#define ROUND(out, in, r) \
|
||||
temp = in ^ ks[2*r]; \
|
||||
out ^= KSLOOKUP( 1, 24 ); \
|
||||
out ^= KSLOOKUP( 3, 16 ); \
|
||||
out ^= KSLOOKUP( 5, 8 ); \
|
||||
out ^= KSLOOKUP( 7, 0 ); \
|
||||
temp = ((in >> 4) | (in << 28)) ^ ks[2*r+1]; \
|
||||
out ^= KSLOOKUP( 0, 24 ); \
|
||||
out ^= KSLOOKUP( 2, 16 ); \
|
||||
out ^= KSLOOKUP( 4, 8 ); \
|
||||
out ^= KSLOOKUP( 6, 0 );
|
||||
|
||||
/* Do the 16 Feistel rounds */
|
||||
ROUND(left, right, 0)
|
||||
ROUND(right, left, 1)
|
||||
ROUND(left, right, 2)
|
||||
ROUND(right, left, 3)
|
||||
ROUND(left, right, 4)
|
||||
ROUND(right, left, 5)
|
||||
ROUND(left, right, 6)
|
||||
ROUND(right, left, 7)
|
||||
ROUND(left, right, 8)
|
||||
ROUND(right, left, 9)
|
||||
ROUND(left, right, 10)
|
||||
ROUND(right, left, 11)
|
||||
ROUND(left, right, 12)
|
||||
ROUND(right, left, 13)
|
||||
ROUND(left, right, 14)
|
||||
ROUND(right, left, 15)
|
||||
|
||||
/* now shift circularly right 3 bits to undo the shifting done
|
||||
** above. switch left and right here.
|
||||
*/
|
||||
temp = (left >> 3) | (left << 29);
|
||||
left = (right >> 3) | (right << 29);
|
||||
right = temp;
|
||||
|
||||
FP(left, right, temp);
|
||||
|
||||
#if defined(_X86_)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
HALFPTR(outbuf)[0] = left;
|
||||
HALFPTR(outbuf)[1] = right;
|
||||
#else
|
||||
if (((ptrdiff_t)inbuf & 0x03) == 0) {
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
HALFPTR(outbuf)[0] = left;
|
||||
HALFPTR(outbuf)[1] = right;
|
||||
} else {
|
||||
outbuf[0] = (BYTE)(left >> 24);
|
||||
outbuf[1] = (BYTE)(left >> 16);
|
||||
outbuf[2] = (BYTE)(left >> 8);
|
||||
outbuf[3] = (BYTE)(left );
|
||||
|
||||
outbuf[4] = (BYTE)(right >> 24);
|
||||
outbuf[5] = (BYTE)(right >> 16);
|
||||
outbuf[6] = (BYTE)(right >> 8);
|
||||
outbuf[7] = (BYTE)(right );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Ackowledgements:
|
||||
** Two ideas used in this implementation were shown to me by Dennis Ferguson
|
||||
** in 1990. He credits them to Richard Outerbridge and Dan Hoey. They were:
|
||||
** 1. The method of computing the Initial and Final permutations.
|
||||
** 2. Circularly rotating the SP tables and the initial values of left and
|
||||
** right to reduce the number of shifts required during the 16 rounds.
|
||||
*/
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* des.h
|
||||
*
|
||||
* header file for DES-150 library
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Nelson B. Bolyard,
|
||||
* nelsonb@iname.com. Portions created by Nelson B. Bolyard are
|
||||
* Copyright (C) 1990, 2000 Nelson B. Bolyard, All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
#ifndef _DES_H_
|
||||
#define _DES_H_ 1
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned int HALF;
|
||||
|
||||
#define HALFPTR(x) ((HALF *)(x))
|
||||
#define SHORTPTR(x) ((unsigned short *)(x))
|
||||
#define BYTEPTR(x) ((BYTE *)(x))
|
||||
|
||||
typedef enum {
|
||||
DES_ENCRYPT = 0x5555,
|
||||
DES_DECRYPT = 0xAAAA
|
||||
} DESDirection;
|
||||
|
||||
typedef void DESFunc(struct DESContextStr *cx, BYTE *out, const BYTE *in,
|
||||
unsigned int len);
|
||||
|
||||
struct DESContextStr {
|
||||
/* key schedule, 16 internal keys, each with 8 6-bit parts */
|
||||
HALF ks0 [32];
|
||||
HALF ks1 [32];
|
||||
HALF ks2 [32];
|
||||
HALF iv [2];
|
||||
DESDirection direction;
|
||||
DESFunc *worker;
|
||||
};
|
||||
|
||||
void DES_MakeSchedule( HALF * ks, const BYTE * key, DESDirection direction);
|
||||
void DES_Do1Block( HALF * ks, const BYTE * inbuf, BYTE * outbuf);
|
||||
|
||||
#endif
|
||||
@@ -1,275 +0,0 @@
|
||||
/*
|
||||
* desblapi.c
|
||||
*
|
||||
* core source file for DES-150 library
|
||||
* Implement DES Modes of Operation and Triple-DES.
|
||||
* Adapt DES-150 to blapi API.
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Nelson B. Bolyard,
|
||||
* nelsonb@iname.com. Portions created by Nelson B. Bolyard are
|
||||
* Copyright (C) 1990, 2000 Nelson B. Bolyard, All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
#include "des.h"
|
||||
#include <stddef.h>
|
||||
#include "secerr.h"
|
||||
|
||||
#if defined(_X86_)
|
||||
/* Intel X86 CPUs do unaligned loads and stores without complaint. */
|
||||
#define COPY8B(to, from, ptr) \
|
||||
HALFPTR(to)[0] = HALFPTR(from)[0]; \
|
||||
HALFPTR(to)[1] = HALFPTR(from)[1];
|
||||
#elif defined(USE_MEMCPY)
|
||||
#define COPY8B(to, from, ptr) memcpy(to, from, 8)
|
||||
#else
|
||||
#define COPY8B(to, from, ptr) \
|
||||
if (((ptrdiff_t)(ptr) & 0x3) == 0) { \
|
||||
HALFPTR(to)[0] = HALFPTR(from)[0]; \
|
||||
HALFPTR(to)[1] = HALFPTR(from)[1]; \
|
||||
} else if (((ptrdiff_t)(ptr) & 0x1) == 0) { \
|
||||
SHORTPTR(to)[0] = SHORTPTR(from)[0]; \
|
||||
SHORTPTR(to)[1] = SHORTPTR(from)[1]; \
|
||||
SHORTPTR(to)[2] = SHORTPTR(from)[2]; \
|
||||
SHORTPTR(to)[3] = SHORTPTR(from)[3]; \
|
||||
} else { \
|
||||
BYTEPTR(to)[0] = BYTEPTR(from)[0]; \
|
||||
BYTEPTR(to)[1] = BYTEPTR(from)[1]; \
|
||||
BYTEPTR(to)[2] = BYTEPTR(from)[2]; \
|
||||
BYTEPTR(to)[3] = BYTEPTR(from)[3]; \
|
||||
BYTEPTR(to)[4] = BYTEPTR(from)[4]; \
|
||||
BYTEPTR(to)[5] = BYTEPTR(from)[5]; \
|
||||
BYTEPTR(to)[6] = BYTEPTR(from)[6]; \
|
||||
BYTEPTR(to)[7] = BYTEPTR(from)[7]; \
|
||||
}
|
||||
#endif
|
||||
#define COPY8BTOHALF(to, from) COPY8B(to, from, from)
|
||||
#define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
|
||||
|
||||
static void
|
||||
DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
while (len) {
|
||||
DES_Do1Block(cx->ks0, in, out);
|
||||
len -= 8;
|
||||
in += 8;
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
while (len) {
|
||||
DES_Do1Block(cx->ks0, in, out);
|
||||
len -= 8;
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks1, out, out);
|
||||
DES_Do1Block(cx->ks2, out, out);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend = in + len;
|
||||
HALF vec[2];
|
||||
|
||||
while (in != bufend) {
|
||||
COPY8BTOHALF(vec, in);
|
||||
in += 8;
|
||||
vec[0] ^= cx->iv[0];
|
||||
vec[1] ^= cx->iv[1];
|
||||
DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
|
||||
COPY8BFROMHALF(out, cx->iv);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend;
|
||||
HALF oldciphertext[2];
|
||||
HALF plaintext [2];
|
||||
|
||||
for (bufend = in + len; in != bufend; ) {
|
||||
oldciphertext[0] = cx->iv[0];
|
||||
oldciphertext[1] = cx->iv[1];
|
||||
COPY8BTOHALF(cx->iv, in);
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
|
||||
plaintext[0] ^= oldciphertext[0];
|
||||
plaintext[1] ^= oldciphertext[1];
|
||||
COPY8BFROMHALF(out, plaintext);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend = in + len;
|
||||
HALF vec[2];
|
||||
|
||||
while (in != bufend) {
|
||||
COPY8BTOHALF(vec, in);
|
||||
in += 8;
|
||||
vec[0] ^= cx->iv[0];
|
||||
vec[1] ^= cx->iv[1];
|
||||
DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
|
||||
DES_Do1Block( cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
|
||||
DES_Do1Block( cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
|
||||
COPY8BFROMHALF(out, cx->iv);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend;
|
||||
HALF oldciphertext[2];
|
||||
HALF plaintext [2];
|
||||
|
||||
for (bufend = in + len; in != bufend; ) {
|
||||
oldciphertext[0] = cx->iv[0];
|
||||
oldciphertext[1] = cx->iv[1];
|
||||
COPY8BTOHALF(cx->iv, in);
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
|
||||
DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
|
||||
DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
|
||||
plaintext[0] ^= oldciphertext[0];
|
||||
plaintext[1] ^= oldciphertext[1];
|
||||
COPY8BFROMHALF(out, plaintext);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
DESContext *
|
||||
DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt)
|
||||
{
|
||||
DESContext *cx = PORT_ZNew(DESContext);
|
||||
DESDirection opposite;
|
||||
if (!cx)
|
||||
return 0;
|
||||
cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
|
||||
opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
|
||||
switch (mode) {
|
||||
case NSS_DES: /* DES ECB */
|
||||
DES_MakeSchedule( cx->ks0, key, cx->direction);
|
||||
cx->worker = &DES_ECB;
|
||||
break;
|
||||
|
||||
case NSS_DES_EDE3: /* DES EDE ECB */
|
||||
cx->worker = &DES_EDE3_ECB;
|
||||
if (encrypt) {
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
|
||||
} else {
|
||||
DES_MakeSchedule(cx->ks2, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
|
||||
}
|
||||
break;
|
||||
|
||||
case NSS_DES_CBC: /* DES CBC */
|
||||
COPY8BTOHALF(cx->iv, iv);
|
||||
cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
break;
|
||||
|
||||
case NSS_DES_EDE3_CBC: /* DES EDE CBC */
|
||||
COPY8BTOHALF(cx->iv, iv);
|
||||
if (encrypt) {
|
||||
cx->worker = &DES_EDE3CBCEn;
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
|
||||
} else {
|
||||
cx->worker = &DES_EDE3CBCDe;
|
||||
DES_MakeSchedule(cx->ks2, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_Free(cx);
|
||||
cx = 0;
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
break;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
DES_DestroyContext(DESContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
|
||||
unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
|
||||
{
|
||||
|
||||
if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
|
||||
cx->direction != DES_ENCRYPT) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->worker(cx, out, in, inLen);
|
||||
if (outLen)
|
||||
*outLen = inLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
|
||||
unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
|
||||
{
|
||||
|
||||
if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
|
||||
cx->direction != DES_DECRYPT) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->worker(cx, out, in, inLen);
|
||||
if (outLen)
|
||||
*outLen = inLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
@@ -1,385 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Diffie-Hellman parameter generation, key generation, and secret derivation.
|
||||
* KEA secret generation and verification.
|
||||
*
|
||||
* $Id: dh.c,v 1.6 2001-09-20 22:14:06 relyea%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secitem.h"
|
||||
#include "mpi.h"
|
||||
#include "mpprime.h"
|
||||
#include "secmpi.h"
|
||||
|
||||
#define DH_SECRET_KEY_LEN 20
|
||||
#define KEA_DERIVED_SECRET_LEN 128
|
||||
|
||||
SECStatus
|
||||
DH_GenParam(int primeLen, DHParams **params)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
DHParams *dhparams;
|
||||
unsigned char *pb = NULL;
|
||||
unsigned char *ab = NULL;
|
||||
unsigned long counter = 0;
|
||||
mp_int p, q, a, h, psub1, test;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
if (!params || primeLen < 0) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams));
|
||||
if (!dhparams) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
dhparams->arena = arena;
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&a) = 0;
|
||||
MP_DIGITS(&h) = 0;
|
||||
MP_DIGITS(&psub1) = 0;
|
||||
MP_DIGITS(&test) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&a) );
|
||||
CHECK_MPI_OK( mp_init(&h) );
|
||||
CHECK_MPI_OK( mp_init(&psub1) );
|
||||
CHECK_MPI_OK( mp_init(&test) );
|
||||
/* generate prime with MPI, uses Miller-Rabin to generate strong prime. */
|
||||
pb = PORT_Alloc(primeLen);
|
||||
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) );
|
||||
pb[0] |= 0x80; /* set high-order bit */
|
||||
pb[primeLen-1] |= 0x01; /* set low-order bit */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) );
|
||||
CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter) );
|
||||
/* construct Sophie-Germain prime q = (p-1)/2. */
|
||||
CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
|
||||
CHECK_MPI_OK( mp_div_2(&psub1, &q) );
|
||||
/* construct a generator from the prime. */
|
||||
ab = PORT_Alloc(primeLen);
|
||||
/* generate a candidate number a in p's field */
|
||||
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(ab, primeLen) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&a, ab, primeLen) );
|
||||
/* force a < p (note that quot(a/p) <= 1) */
|
||||
if ( mp_cmp(&a, &p) > 0 )
|
||||
CHECK_MPI_OK( mp_sub(&a, &p, &a) );
|
||||
do {
|
||||
/* check that a is in the range [2..p-1] */
|
||||
if ( mp_cmp_d(&a, 2) < 0 || mp_cmp(&a, &psub1) >= 0) {
|
||||
/* a is outside of the allowed range. Set a=3 and keep going. */
|
||||
mp_set(&a, 3);
|
||||
}
|
||||
/* if a**q mod p != 1 then a is a generator */
|
||||
CHECK_MPI_OK( mp_exptmod(&a, &q, &p, &test) );
|
||||
if ( mp_cmp_d(&test, 1) != 0 )
|
||||
break;
|
||||
/* increment the candidate and try again. */
|
||||
CHECK_MPI_OK( mp_add_d(&a, 1, &a) );
|
||||
} while (PR_TRUE);
|
||||
MPINT_TO_SECITEM(&p, &dhparams->prime, arena);
|
||||
MPINT_TO_SECITEM(&a, &dhparams->base, arena);
|
||||
*params = dhparams;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&a);
|
||||
mp_clear(&h);
|
||||
mp_clear(&psub1);
|
||||
mp_clear(&test);
|
||||
if (pb) PORT_ZFree(pb, primeLen);
|
||||
if (ab) PORT_ZFree(ab, primeLen);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_NewKey(DHParams *params, DHPrivateKey **privKey)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
DHPrivateKey *key;
|
||||
mp_int g, xa, p, Ya;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
if (!params || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey));
|
||||
if (!key) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
key->arena = arena;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&xa) = 0;
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Ya) = 0;
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&xa) );
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Ya) );
|
||||
/* Set private key's p */
|
||||
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->prime, ¶ms->prime) );
|
||||
SECITEM_TO_MPINT(key->prime, &p);
|
||||
/* Set private key's g */
|
||||
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, ¶ms->base) );
|
||||
SECITEM_TO_MPINT(key->base, &g);
|
||||
/* Generate private key xa */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DH_SECRET_KEY_LEN);
|
||||
RNG_GenerateGlobalRandomBytes(key->privateValue.data,
|
||||
key->privateValue.len);
|
||||
SECITEM_TO_MPINT( key->privateValue, &xa );
|
||||
/* xa < p */
|
||||
CHECK_MPI_OK( mp_mod(&xa, &p, &xa) );
|
||||
/* Compute public key Ya = g ** xa mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) );
|
||||
MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena);
|
||||
*privKey = key;
|
||||
cleanup:
|
||||
mp_clear(&g);
|
||||
mp_clear(&xa);
|
||||
mp_clear(&p);
|
||||
mp_clear(&Ya);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_Derive(SECItem *publicValue,
|
||||
SECItem *prime,
|
||||
SECItem *privateValue,
|
||||
SECItem *derivedSecret,
|
||||
unsigned int maxOutBytes)
|
||||
{
|
||||
mp_int p, Xa, Yb, ZZ;
|
||||
mp_err err = MP_OKAY;
|
||||
unsigned int len = 0, nb;
|
||||
unsigned char *secret = NULL;
|
||||
if (!publicValue || !prime || !privateValue || !derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Xa) = 0;
|
||||
MP_DIGITS(&Yb) = 0;
|
||||
MP_DIGITS(&ZZ) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Xa) );
|
||||
CHECK_MPI_OK( mp_init(&Yb) );
|
||||
CHECK_MPI_OK( mp_init(&ZZ) );
|
||||
SECITEM_TO_MPINT(*publicValue, &Yb);
|
||||
SECITEM_TO_MPINT(*privateValue, &Xa);
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
/* ZZ = (Yb)**Xa mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&Yb, &Xa, &p, &ZZ) );
|
||||
/* number of bytes in the derived secret */
|
||||
len = mp_unsigned_octet_size(&ZZ);
|
||||
/* allocate a buffer which can hold the entire derived secret. */
|
||||
secret = PORT_Alloc(len);
|
||||
/* grab the derived secret */
|
||||
err = mp_to_unsigned_octets(&ZZ, secret, len);
|
||||
if (err >= 0) err = MP_OKAY;
|
||||
/* Take minimum of bytes requested and bytes in derived secret,
|
||||
** if maxOutBytes is 0 take all of the bytes from the derived secret.
|
||||
*/
|
||||
if (maxOutBytes > 0)
|
||||
nb = PR_MIN(len, maxOutBytes);
|
||||
else
|
||||
nb = len;
|
||||
SECITEM_AllocItem(NULL, derivedSecret, nb);
|
||||
memcpy(derivedSecret->data, secret, nb);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&Xa);
|
||||
mp_clear(&Yb);
|
||||
mp_clear(&ZZ);
|
||||
if (secret) {
|
||||
/* free the buffer allocated for the full secret. */
|
||||
PORT_ZFree(secret, len);
|
||||
}
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
if (derivedSecret->data)
|
||||
PORT_ZFree(derivedSecret->data, derivedSecret->len);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
KEA_Derive(SECItem *prime,
|
||||
SECItem *public1,
|
||||
SECItem *public2,
|
||||
SECItem *private1,
|
||||
SECItem *private2,
|
||||
SECItem *derivedSecret)
|
||||
{
|
||||
mp_int p, Y, R, r, x, t, u, w;
|
||||
mp_err err;
|
||||
unsigned char *secret = NULL;
|
||||
unsigned int len = 0, offset;
|
||||
if (!prime || !public1 || !public2 || !private1 || !private2 ||
|
||||
!derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Y) = 0;
|
||||
MP_DIGITS(&R) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&t) = 0;
|
||||
MP_DIGITS(&u) = 0;
|
||||
MP_DIGITS(&w) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Y) );
|
||||
CHECK_MPI_OK( mp_init(&R) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&x) );
|
||||
CHECK_MPI_OK( mp_init(&t) );
|
||||
CHECK_MPI_OK( mp_init(&u) );
|
||||
CHECK_MPI_OK( mp_init(&w) );
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
SECITEM_TO_MPINT(*public1, &Y);
|
||||
SECITEM_TO_MPINT(*public2, &R);
|
||||
SECITEM_TO_MPINT(*private1, &r);
|
||||
SECITEM_TO_MPINT(*private2, &x);
|
||||
/* t = DH(Y, r, p) = Y ** r mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&Y, &r, &p, &t) );
|
||||
/* u = DH(R, x, p) = R ** x mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&R, &x, &p, &u) );
|
||||
/* w = (t + u) mod p */
|
||||
CHECK_MPI_OK( mp_addmod(&t, &u, &p, &w) );
|
||||
/* allocate a buffer for the full derived secret */
|
||||
len = mp_unsigned_octet_size(&w);
|
||||
secret = PORT_Alloc(len);
|
||||
/* grab the secret */
|
||||
err = mp_to_unsigned_octets(&w, secret, len);
|
||||
if (err > 0) err = MP_OKAY;
|
||||
/* allocate output buffer */
|
||||
SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN);
|
||||
memset(derivedSecret->data, 0, derivedSecret->len);
|
||||
/* copy in the 128 lsb of the secret */
|
||||
if (len >= KEA_DERIVED_SECRET_LEN) {
|
||||
memcpy(derivedSecret->data, secret + (len - KEA_DERIVED_SECRET_LEN),
|
||||
KEA_DERIVED_SECRET_LEN);
|
||||
} else {
|
||||
offset = KEA_DERIVED_SECRET_LEN - len;
|
||||
memcpy(derivedSecret->data + offset, secret, len);
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&Y);
|
||||
mp_clear(&R);
|
||||
mp_clear(&r);
|
||||
mp_clear(&x);
|
||||
mp_clear(&t);
|
||||
mp_clear(&u);
|
||||
mp_clear(&w);
|
||||
if (secret)
|
||||
PORT_ZFree(secret, len);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PRBool
|
||||
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
|
||||
{
|
||||
mp_int p, q, y, r;
|
||||
mp_err err;
|
||||
int cmp = 1; /* default is false */
|
||||
if (!Y || !prime || !subPrime) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&y) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
SECITEM_TO_MPINT(*subPrime, &q);
|
||||
SECITEM_TO_MPINT(*Y, &y);
|
||||
/* compute r = y**q mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&y, &q, &p, &r) );
|
||||
/* compare to 1 */
|
||||
cmp = mp_cmp_d(&r, 1);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return PR_FALSE;
|
||||
}
|
||||
return (cmp == 0) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
SECStatus
|
||||
DH_GenParam(int primeLen, DHParams ** params)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_NewKey(DHParams * params,
|
||||
DHPrivateKey ** privKey)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_Derive(SECItem * publicValue,
|
||||
SECItem * prime,
|
||||
SECItem * privateValue,
|
||||
SECItem * derivedSecret,
|
||||
unsigned int maxOutBytes)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
KEA_Derive(SECItem *prime,
|
||||
SECItem *public1,
|
||||
SECItem *public2,
|
||||
SECItem *private1,
|
||||
SECItem *private2,
|
||||
SECItem *derivedSecret)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
PRBool
|
||||
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return PR_FALSE;
|
||||
}
|
||||
@@ -1,420 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: dsa.c,v 1.11 2003-02-25 23:45:23 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prinit.h"
|
||||
#include "blapi.h"
|
||||
#include "nssilock.h"
|
||||
#include "secitem.h"
|
||||
#include "blapi.h"
|
||||
#include "mpi.h"
|
||||
|
||||
/* XXX to be replaced by define in blapit.h */
|
||||
#define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
#define CHECKOK(func) if (MP_OKAY > (err = func)) goto cleanup
|
||||
|
||||
#define SECITEM_TO_MPINT(it, mp) \
|
||||
CHECKOK(mp_read_unsigned_octets((mp), (it).data, (it).len))
|
||||
|
||||
/* DSA-specific random number functions defined in prng_fips1861.c. */
|
||||
extern SECStatus
|
||||
DSA_RandomUpdate(void *data, size_t bytes, unsigned char *q);
|
||||
|
||||
extern SECStatus
|
||||
DSA_GenerateGlobalRandomBytes(void *dest, size_t len, unsigned char *q);
|
||||
|
||||
static void translate_mpi_error(mp_err err)
|
||||
{
|
||||
switch (err) {
|
||||
case MP_MEM: PORT_SetError(SEC_ERROR_NO_MEMORY); break;
|
||||
case MP_RANGE: PORT_SetError(SEC_ERROR_BAD_DATA); break;
|
||||
case MP_BADARG: PORT_SetError(SEC_ERROR_INVALID_ARGS); break;
|
||||
default: PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); break;
|
||||
}
|
||||
}
|
||||
|
||||
SECStatus
|
||||
dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey,
|
||||
const unsigned char *xb)
|
||||
{
|
||||
unsigned int y_len;
|
||||
mp_int p, g;
|
||||
mp_int x, y;
|
||||
mp_err err;
|
||||
PRArenaPool *arena;
|
||||
DSAPrivateKey *key;
|
||||
/* Check args. */
|
||||
if (!params || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize an arena for the DSA key. */
|
||||
arena = PORT_NewArena(NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
|
||||
if (!key) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
key->params.arena = arena;
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
CHECKOK( mp_init(&p) );
|
||||
CHECKOK( mp_init(&g) );
|
||||
CHECKOK( mp_init(&x) );
|
||||
CHECKOK( mp_init(&y) );
|
||||
/* Copy over the PQG params */
|
||||
CHECKOK( SECITEM_CopyItem(arena, &key->params.prime, ¶ms->prime) );
|
||||
CHECKOK( SECITEM_CopyItem(arena, &key->params.subPrime, ¶ms->subPrime));
|
||||
CHECKOK( SECITEM_CopyItem(arena, &key->params.base, ¶ms->base) );
|
||||
/* Convert stored p, g, and received x into MPI integers. */
|
||||
SECITEM_TO_MPINT(params->prime, &p);
|
||||
SECITEM_TO_MPINT(params->base, &g);
|
||||
CHECKOK( mp_read_unsigned_octets(&x, xb, DSA_SUBPRIME_LEN) );
|
||||
/* Store x in private key */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DSA_SUBPRIME_LEN);
|
||||
memcpy(key->privateValue.data, xb, DSA_SUBPRIME_LEN);
|
||||
/* Compute public key y = g**x mod p */
|
||||
CHECKOK( mp_exptmod(&g, &x, &p, &y) );
|
||||
/* Store y in public key */
|
||||
y_len = mp_unsigned_octet_size(&y);
|
||||
SECITEM_AllocItem(arena, &key->publicValue, y_len);
|
||||
err = mp_to_unsigned_octets(&y, key->publicValue.data, y_len);
|
||||
/* mp_to_unsigned_octets returns bytes written (y_len) if okay */
|
||||
if (err < 0) goto cleanup; else err = MP_OKAY;
|
||||
*privKey = key;
|
||||
key = NULL;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&y);
|
||||
if (key)
|
||||
PORT_FreeArena(key->params.arena, PR_TRUE);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate and return a new DSA public and private key pair,
|
||||
** both of which are encoded into a single DSAPrivateKey struct.
|
||||
** "params" is a pointer to the PQG parameters for the domain
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
unsigned char seed[DSA_SUBPRIME_LEN];
|
||||
/* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
|
||||
if (DSA_GenerateGlobalRandomBytes(seed, DSA_SUBPRIME_LEN,
|
||||
params->subPrime.data))
|
||||
return SECFailure;
|
||||
/* Generate a new DSA key using random seed. */
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes long */
|
||||
SECStatus
|
||||
DSA_NewKeyFromSeed(const PQGParams *params,
|
||||
const unsigned char *seed,
|
||||
DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
|
||||
const unsigned char *kb)
|
||||
{
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int x, k; /* private key & pseudo-random integer */
|
||||
mp_int r, s; /* tuple (r, s) is signature) */
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len != DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&s) = 0;
|
||||
CHECKOK( mp_init(&p) );
|
||||
CHECKOK( mp_init(&q) );
|
||||
CHECKOK( mp_init(&g) );
|
||||
CHECKOK( mp_init(&x) );
|
||||
CHECKOK( mp_init(&k) );
|
||||
CHECKOK( mp_init(&r) );
|
||||
CHECKOK( mp_init(&s) );
|
||||
/*
|
||||
** Convert stored PQG and private key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->privateValue, &x);
|
||||
CHECKOK( mp_read_unsigned_octets(&k, kb, DSA_SUBPRIME_LEN) );
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 1
|
||||
**
|
||||
** r = (g**k mod p) mod q
|
||||
*/
|
||||
CHECKOK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */
|
||||
CHECKOK( mp_mod(&r, &q, &r) ); /* r = r mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 2
|
||||
**
|
||||
** s = (k**-1 * (SHA1(M) + x*r)) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
|
||||
CHECKOK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */
|
||||
CHECKOK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */
|
||||
CHECKOK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */
|
||||
CHECKOK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */
|
||||
/*
|
||||
** verify r != 0 and s != 0
|
||||
** mentioned as optional in FIPS 186-1.
|
||||
*/
|
||||
if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
rv = SECFailure;
|
||||
goto cleanup;
|
||||
}
|
||||
/*
|
||||
** Step 4
|
||||
**
|
||||
** Signature is tuple (r, s)
|
||||
*/
|
||||
err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN,
|
||||
DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = MP_OKAY;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&k);
|
||||
mp_clear(&r);
|
||||
mp_clear(&s);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 20 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
** On output, signature->len == size of signature in buffer.
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
|
||||
{
|
||||
SECStatus rv;
|
||||
int retries = 10;
|
||||
unsigned char kSeed[DSA_SUBPRIME_LEN];
|
||||
|
||||
PORT_SetError(0);
|
||||
do {
|
||||
rv = DSA_GenerateGlobalRandomBytes(kSeed, DSA_SUBPRIME_LEN,
|
||||
key->params.subPrime.data);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
rv = dsa_SignDigest(key, signature, digest, kSeed);
|
||||
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
|
||||
--retries > 0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes. */
|
||||
SECStatus
|
||||
DSA_SignDigestWithSeed(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_SignDigest(key, signature, digest, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 20 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
|
||||
const SECItem *digest)
|
||||
{
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int r_, s_; /* tuple (r', s') is received signature) */
|
||||
mp_int u1, u2, v, w; /* intermediate values used in verification */
|
||||
mp_int y; /* public key */
|
||||
mp_err err;
|
||||
SECStatus verified = SECFailure;
|
||||
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len != DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r_) = 0;
|
||||
MP_DIGITS(&s_) = 0;
|
||||
MP_DIGITS(&u1) = 0;
|
||||
MP_DIGITS(&u2) = 0;
|
||||
MP_DIGITS(&v) = 0;
|
||||
MP_DIGITS(&w) = 0;
|
||||
CHECKOK( mp_init(&p) );
|
||||
CHECKOK( mp_init(&q) );
|
||||
CHECKOK( mp_init(&g) );
|
||||
CHECKOK( mp_init(&y) );
|
||||
CHECKOK( mp_init(&r_) );
|
||||
CHECKOK( mp_init(&s_) );
|
||||
CHECKOK( mp_init(&u1) );
|
||||
CHECKOK( mp_init(&u2) );
|
||||
CHECKOK( mp_init(&v) );
|
||||
CHECKOK( mp_init(&w) );
|
||||
/*
|
||||
** Convert stored PQG and public key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->publicValue, &y);
|
||||
/*
|
||||
** Convert received signature (r', s') into MPI integers.
|
||||
*/
|
||||
CHECKOK( mp_read_unsigned_octets(&r_, signature->data, DSA_SUBPRIME_LEN) );
|
||||
CHECKOK( mp_read_unsigned_octets(&s_, signature->data + DSA_SUBPRIME_LEN,
|
||||
DSA_SUBPRIME_LEN) );
|
||||
/*
|
||||
** Verify that 0 < r' < q and 0 < s' < q
|
||||
*/
|
||||
if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
|
||||
mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0)
|
||||
goto cleanup; /* will return verified == SECFailure */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 1
|
||||
**
|
||||
** w = (s')**-1 mod q
|
||||
*/
|
||||
CHECKOK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 2
|
||||
**
|
||||
** u1 = ((SHA1(M')) * w) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
|
||||
CHECKOK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 3
|
||||
**
|
||||
** u2 = ((r') * w) mod q
|
||||
*/
|
||||
CHECKOK( mp_mulmod(&r_, &w, &q, &u2) );
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 4
|
||||
**
|
||||
** v = ((g**u1 * y**u2) mod p) mod q
|
||||
*/
|
||||
CHECKOK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */
|
||||
CHECKOK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */
|
||||
CHECKOK( mp_mulmod(&g, &y, &p, &v) ); /* v = g * y mod p */
|
||||
CHECKOK( mp_mod(&v, &q, &v) ); /* v = v mod q */
|
||||
/*
|
||||
** Verification: v == r'
|
||||
*/
|
||||
if (mp_cmp(&v, &r_)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
verified = SECFailure; /* Signature failed to verify. */
|
||||
} else {
|
||||
verified = SECSuccess; /* Signature verified. */
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r_);
|
||||
mp_clear(&s_);
|
||||
mp_clear(&u1);
|
||||
mp_clear(&u2);
|
||||
mp_clear(&v);
|
||||
mp_clear(&w);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
}
|
||||
return verified;
|
||||
}
|
||||
@@ -1,977 +0,0 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Elliptic Curve Cryptography library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "blapi.h"
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
#include "secmpi.h"
|
||||
#include "secitem.h"
|
||||
#include "ec.h"
|
||||
#include "GFp_ecl.h"
|
||||
#include "GF2m_ecl.h"
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
/*
|
||||
* Returns true if pointP is the point at infinity, false otherwise
|
||||
*/
|
||||
PRBool
|
||||
ec_point_at_infinity(SECItem *pointP)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < pointP->len; i++) {
|
||||
if (pointP->data[i] != 0x00) return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes point addition R = P + Q for the curve whose
|
||||
* parameters are encoded in params. Two or more of P, Q,
|
||||
* R may point to the same memory location.
|
||||
*/
|
||||
SECStatus
|
||||
ec_point_add(ECParams *params, SECItem *pointP,
|
||||
SECItem *pointQ, SECItem *pointR)
|
||||
{
|
||||
mp_int Px, Py, Qx, Qy, Rx, Ry;
|
||||
mp_int irreducible, a;
|
||||
SECStatus rv = SECFailure;
|
||||
mp_err err = MP_OKAY;
|
||||
int len;
|
||||
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
|
||||
printf("ec_point_add: params [len=%d]:", params->DEREncoding.len);
|
||||
for (i = 0; i < params->DEREncoding.len; i++)
|
||||
printf("%02x:", params->DEREncoding.data[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("ec_point_add: pointP [len=%d]:", pointP->len);
|
||||
for (i = 0; i < pointP->len; i++)
|
||||
printf("%02x:", pointP->data[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("ec_point_add: pointQ [len=%d]:", pointQ->len);
|
||||
for (i = 0; i < pointQ->len; i++)
|
||||
printf("%02x:", pointQ->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/* NOTE: We only support prime field curves for now */
|
||||
len = (params->fieldID.size + 7) >> 3;
|
||||
if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
|
||||
(pointP->len != (2 * len + 1)) ||
|
||||
(pointQ->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
|
||||
(pointQ->len != (2 * len + 1))) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
MP_DIGITS(&Px) = 0;
|
||||
MP_DIGITS(&Py) = 0;
|
||||
MP_DIGITS(&Qx) = 0;
|
||||
MP_DIGITS(&Qy) = 0;
|
||||
MP_DIGITS(&Rx) = 0;
|
||||
MP_DIGITS(&Ry) = 0;
|
||||
MP_DIGITS(&irreducible) = 0;
|
||||
MP_DIGITS(&a) = 0;
|
||||
CHECK_MPI_OK( mp_init(&Px) );
|
||||
CHECK_MPI_OK( mp_init(&Py) );
|
||||
CHECK_MPI_OK( mp_init(&Qx) );
|
||||
CHECK_MPI_OK( mp_init(&Qy) );
|
||||
CHECK_MPI_OK( mp_init(&Rx) );
|
||||
CHECK_MPI_OK( mp_init(&Ry) );
|
||||
CHECK_MPI_OK( mp_init(&irreducible) );
|
||||
CHECK_MPI_OK( mp_init(&a) );
|
||||
|
||||
/* Initialize Px and Py */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
|
||||
/* Initialize Qx and Qy */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Qx, pointQ->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Qy, pointQ->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
|
||||
/* Set up the curve coefficient */
|
||||
SECITEM_TO_MPINT( params->curve.a, &a );
|
||||
|
||||
/* Compute R = P + Q */
|
||||
if (params->fieldID.type == ec_field_GFp) {
|
||||
SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
|
||||
if (GFp_ec_pt_add(&irreducible, &a, &Px, &Py, &Qx, &Qy,
|
||||
&Rx, &Ry) != SECSuccess)
|
||||
goto cleanup;
|
||||
} else {
|
||||
SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
|
||||
if (GF2m_ec_pt_add(&irreducible, &a, &Px, &Py, &Qx, &Qy, &Rx, &Ry)
|
||||
!= SECSuccess)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Construct the SECItem representation of the result */
|
||||
pointR->data[0] = EC_POINT_FORM_UNCOMPRESSED;
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Rx, pointR->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Ry, pointR->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
rv = SECSuccess;
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ec_point_add: pointR [len=%d]:", pointR->len);
|
||||
for (i = 0; i < pointR->len; i++)
|
||||
printf("%02x:", pointR->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
mp_clear(&Px);
|
||||
mp_clear(&Py);
|
||||
mp_clear(&Qx);
|
||||
mp_clear(&Qy);
|
||||
mp_clear(&Rx);
|
||||
mp_clear(&Ry);
|
||||
mp_clear(&irreducible);
|
||||
mp_clear(&a);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes scalar point multiplication pointQ = k * pointP for
|
||||
* the curve whose parameters are encoded in params.
|
||||
*/
|
||||
SECStatus
|
||||
ec_point_mul(ECParams *params, mp_int *k,
|
||||
SECItem *pointP, SECItem *pointQ)
|
||||
{
|
||||
mp_int Px, Py, Qx, Qy;
|
||||
mp_int irreducible, a, b;
|
||||
SECStatus rv = SECFailure;
|
||||
mp_err err = MP_OKAY;
|
||||
int len;
|
||||
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
char mpstr[256];
|
||||
|
||||
printf("ec_point_mul: params [len=%d]:", params->DEREncoding.len);
|
||||
for (i = 0; i < params->DEREncoding.len; i++)
|
||||
printf("%02x:", params->DEREncoding.data[i]);
|
||||
printf("\n");
|
||||
|
||||
mp_tohex(k, mpstr);
|
||||
printf("ec_point_mul: scalar : %s\n", mpstr);
|
||||
mp_todecimal(k, mpstr);
|
||||
printf("ec_point_mul: scalar : %s (dec)\n", mpstr);
|
||||
|
||||
printf("ec_point_mul: pointP [len=%d]:", pointP->len);
|
||||
for (i = 0; i < pointP->len; i++)
|
||||
printf("%02x:", pointP->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/* NOTE: We only support prime field curves for now */
|
||||
len = (params->fieldID.size + 7) >> 3;
|
||||
if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
|
||||
(pointP->len != (2 * len + 1))) {
|
||||
return SECFailure;
|
||||
};
|
||||
|
||||
MP_DIGITS(&Px) = 0;
|
||||
MP_DIGITS(&Py) = 0;
|
||||
MP_DIGITS(&Qx) = 0;
|
||||
MP_DIGITS(&Qy) = 0;
|
||||
MP_DIGITS(&irreducible) = 0;
|
||||
MP_DIGITS(&a) = 0;
|
||||
MP_DIGITS(&b) = 0;
|
||||
CHECK_MPI_OK( mp_init(&Px) );
|
||||
CHECK_MPI_OK( mp_init(&Py) );
|
||||
CHECK_MPI_OK( mp_init(&Qx) );
|
||||
CHECK_MPI_OK( mp_init(&Qy) );
|
||||
CHECK_MPI_OK( mp_init(&irreducible) );
|
||||
CHECK_MPI_OK( mp_init(&a) );
|
||||
CHECK_MPI_OK( mp_init(&b) );
|
||||
|
||||
/* Initialize Px and Py */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
|
||||
/* Set up mp_ints containing the curve coefficients */
|
||||
SECITEM_TO_MPINT( params->curve.a, &a );
|
||||
SECITEM_TO_MPINT( params->curve.b, &b );
|
||||
|
||||
/* Compute Q = k * P */
|
||||
if (params->fieldID.type == ec_field_GFp) {
|
||||
SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
|
||||
if (GFp_ec_pt_mul(&irreducible, &a, &b, &Px, &Py, k, &Qx, &Qy)
|
||||
!= SECSuccess)
|
||||
goto cleanup;
|
||||
} else {
|
||||
SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
|
||||
if (GF2m_ec_pt_mul(&irreducible, &a, &b, &Px, &Py, k, &Qx, &Qy)
|
||||
!= SECSuccess) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct the SECItem representation of point Q */
|
||||
pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
|
||||
rv = SECSuccess;
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ec_point_mul: pointQ [len=%d]:", pointQ->len);
|
||||
for (i = 0; i < pointQ->len; i++)
|
||||
printf("%02x:", pointQ->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
mp_clear(&Px);
|
||||
mp_clear(&Py);
|
||||
mp_clear(&Qx);
|
||||
mp_clear(&Qy);
|
||||
mp_clear(&irreducible);
|
||||
mp_clear(&a);
|
||||
mp_clear(&b);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static unsigned char bitmask[] = {
|
||||
0xff, 0x7f, 0x3f, 0x1f,
|
||||
0x0f, 0x07, 0x03, 0x01
|
||||
};
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
/* Generates a new EC key pair. The private key is a supplied
|
||||
* random value (in seed) and the public key is the result of
|
||||
* performing a scalar point multiplication of that value with
|
||||
* the curve's base point.
|
||||
*/
|
||||
SECStatus
|
||||
EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
|
||||
const unsigned char *seed, int seedlen)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
PRArenaPool *arena;
|
||||
ECPrivateKey *key;
|
||||
mp_int k;
|
||||
mp_err err = MP_OKAY;
|
||||
int len;
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("EC_NewKeyFromSeed called\n");
|
||||
#endif
|
||||
|
||||
if (!ecParams || !privKey || !seed || (seedlen < 0)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Initialize an arena for the EC key. */
|
||||
if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
|
||||
return SECFailure;
|
||||
|
||||
key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
|
||||
if (!key) {
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
|
||||
/* Copy all of the fields from the ECParams argument to the
|
||||
* ECParams structure within the private key.
|
||||
*/
|
||||
key->ecParams.arena = arena;
|
||||
key->ecParams.type = ecParams->type;
|
||||
key->ecParams.fieldID.size = ecParams->fieldID.size;
|
||||
key->ecParams.fieldID.type = ecParams->fieldID.type;
|
||||
if (ecParams->fieldID.type == ec_field_GFp) {
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
|
||||
&ecParams->fieldID.u.prime));
|
||||
} else {
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
|
||||
&ecParams->fieldID.u.poly));
|
||||
}
|
||||
key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
|
||||
key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
|
||||
key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
|
||||
&ecParams->curve.a));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
|
||||
&ecParams->curve.b));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
|
||||
&ecParams->curve.seed));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
|
||||
&ecParams->base));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
|
||||
&ecParams->order));
|
||||
key->ecParams.cofactor = ecParams->cofactor;
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
|
||||
&ecParams->DEREncoding));
|
||||
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
SECITEM_AllocItem(arena, &key->privateValue, len);
|
||||
SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1);
|
||||
|
||||
/* Copy private key */
|
||||
if (seedlen >= len) {
|
||||
memcpy(key->privateValue.data, seed, len);
|
||||
} else {
|
||||
memset(key->privateValue.data, 0, (len - seedlen));
|
||||
memcpy(key->privateValue.data + (len - seedlen), seed, seedlen);
|
||||
}
|
||||
|
||||
/* Compute corresponding public key */
|
||||
MP_DIGITS(&k) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
|
||||
(mp_size) len) );
|
||||
|
||||
rv = ec_point_mul(ecParams, &k, &(ecParams->base), &(key->publicValue));
|
||||
if (rv != SECSuccess) goto cleanup;
|
||||
*privKey = key;
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("EC_NewKeyFromSeed returning %s\n",
|
||||
(rv == SECSuccess) ? "success" : "failure");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
/* Generates a new EC key pair. The private key is a random value and
|
||||
* the public key is the result of performing a scalar point multiplication
|
||||
* of that value with the curve's base point.
|
||||
*/
|
||||
SECStatus
|
||||
EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
int len;
|
||||
unsigned char *seed;
|
||||
|
||||
if (!ecParams || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Generate random private key */
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
if ((seed = PORT_Alloc(len)) == NULL) goto cleanup;
|
||||
if (RNG_GenerateGlobalRandomBytes(seed, len) != SECSuccess) goto cleanup;
|
||||
|
||||
/* Fit private key to the field size */
|
||||
seed[0] &= bitmask[len * 8 - ecParams->fieldID.size];
|
||||
rv = EC_NewKeyFromSeed(ecParams, privKey, seed, len);
|
||||
|
||||
cleanup:
|
||||
if (!seed) {
|
||||
PORT_ZFree(seed, len);
|
||||
}
|
||||
#if EC_DEBUG
|
||||
printf("EC_NewKey returning %s\n",
|
||||
(rv == SECSuccess) ? "success" : "failure");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of
|
||||
* X9.63. The ECDH primitive when used without the cofactor does
|
||||
* not address small subgroup attacks, which may occur when the
|
||||
* public key is not valid. These attacks can be prevented by
|
||||
* validating the public key before using ECDH.
|
||||
*/
|
||||
SECStatus
|
||||
EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
|
||||
{
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
if (!ecParams || !publicValue) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* XXX Add actual checks here. */
|
||||
return SECSuccess;
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
return SECFailure;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
}
|
||||
|
||||
/*
|
||||
** Performs an ECDH key derivation by computing the scalar point
|
||||
** multiplication of privateValue and publicValue (with or without the
|
||||
** cofactor) and returns the x-coordinate of the resulting elliptic
|
||||
** curve point in derived secret. If successful, derivedSecret->data
|
||||
** is set to the address of the newly allocated buffer containing the
|
||||
** derived secret, and derivedSecret->len is the size of the secret
|
||||
** produced. It is the caller's responsibility to free the allocated
|
||||
** buffer containing the derived secret.
|
||||
*/
|
||||
SECStatus
|
||||
ECDH_Derive(SECItem *publicValue,
|
||||
ECParams *ecParams,
|
||||
SECItem *privateValue,
|
||||
PRBool withCofactor,
|
||||
SECItem *derivedSecret)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
unsigned int len = 0;
|
||||
SECItem pointQ = {siBuffer, NULL, 0};
|
||||
mp_int k; /* to hold the private value */
|
||||
mp_int cofactor;
|
||||
mp_err err = MP_OKAY;
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (!publicValue || !ecParams || !privateValue ||
|
||||
!derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
pointQ.len = 2*len + 1;
|
||||
if ((pointQ.data = PORT_Alloc(2*len + 1)) == NULL) goto cleanup;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
|
||||
(mp_size) privateValue->len) );
|
||||
|
||||
if (withCofactor && (ecParams->cofactor != 1)) {
|
||||
/* multiply k with the cofactor */
|
||||
MP_DIGITS(&cofactor) = 0;
|
||||
CHECK_MPI_OK( mp_init(&cofactor) );
|
||||
mp_set(&cofactor, ecParams->cofactor);
|
||||
CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
|
||||
}
|
||||
|
||||
/* Multiply our private key and peer's public point */
|
||||
if ((ec_point_mul(ecParams, &k, publicValue, &pointQ) != SECSuccess) ||
|
||||
ec_point_at_infinity(&pointQ))
|
||||
goto cleanup;
|
||||
|
||||
/* Allocate memory for the derived secret and copy
|
||||
* the x co-ordinate of pointQ into it.
|
||||
*/
|
||||
SECITEM_AllocItem(NULL, derivedSecret, len);
|
||||
memcpy(derivedSecret->data, pointQ.data + 1, len);
|
||||
|
||||
rv = SECSuccess;
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("derived_secret:\n");
|
||||
for (i = 0; i < derivedSecret->len; i++)
|
||||
printf("%02x:", derivedSecret->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
|
||||
if (pointQ.data) {
|
||||
PORT_ZFree(pointQ.data, 2*len + 1);
|
||||
}
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Computes the ECDSA signature (a concatenation of two values r and s)
|
||||
* on the digest using the given key and the random value kb (used in
|
||||
* computing s).
|
||||
*/
|
||||
SECStatus
|
||||
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
|
||||
const SECItem *digest, const unsigned char *kb, const int kblen)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
mp_int x1;
|
||||
mp_int d, k; /* private key, random integer */
|
||||
mp_int r, s; /* tuple (r, s) is the signature */
|
||||
mp_int n;
|
||||
mp_err err = MP_OKAY;
|
||||
ECParams *ecParams = NULL;
|
||||
SECItem kGpoint = { siBuffer, NULL, 0};
|
||||
int len = 0;
|
||||
|
||||
#if EC_DEBUG
|
||||
char mpstr[256];
|
||||
#endif
|
||||
|
||||
/* Check args */
|
||||
if (!key || !signature || !digest || !kb || (kblen < 0) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ecParams = &(key->ecParams);
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
if (signature->len < 2*len) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&d) = 0;
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&s) = 0;
|
||||
MP_DIGITS(&n) = 0;
|
||||
CHECK_MPI_OK( mp_init(&x1) );
|
||||
CHECK_MPI_OK( mp_init(&d) );
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&s) );
|
||||
CHECK_MPI_OK( mp_init(&n) );
|
||||
|
||||
SECITEM_TO_MPINT( ecParams->order, &n );
|
||||
SECITEM_TO_MPINT( key->privateValue, &d );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
|
||||
/* Make sure k is in the interval [1, n-1] */
|
||||
if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.2, Step 2
|
||||
**
|
||||
** Compute kG
|
||||
*/
|
||||
kGpoint.len = 2*len + 1;
|
||||
kGpoint.data = PORT_Alloc(2*len + 1);
|
||||
if ((kGpoint.data == NULL) ||
|
||||
(ec_point_mul(ecParams, &k, &(ecParams->base), &kGpoint)
|
||||
!= SECSuccess))
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 1
|
||||
**
|
||||
** Extract the x co-ordinate of kG into x1
|
||||
*/
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
|
||||
(mp_size) len) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 2
|
||||
**
|
||||
** r = x1 mod n NOTE: n is the order of the curve
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mod(&x1, &n, &r) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 3
|
||||
**
|
||||
** verify r != 0
|
||||
*/
|
||||
if (mp_cmp_z(&r) == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 4
|
||||
**
|
||||
** s = (k**-1 * (SHA1(M) + d*r)) mod n
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
|
||||
|
||||
#if EC_DEBUG
|
||||
mp_todecimal(&n, mpstr);
|
||||
printf("n : %s (dec)\n", mpstr);
|
||||
mp_todecimal(&d, mpstr);
|
||||
printf("d : %s (dec)\n", mpstr);
|
||||
mp_tohex(&x1, mpstr);
|
||||
printf("x1: %s\n", mpstr);
|
||||
mp_todecimal(&s, mpstr);
|
||||
printf("digest: %s (decimal)\n", mpstr);
|
||||
mp_todecimal(&r, mpstr);
|
||||
printf("r : %s (dec)\n", mpstr);
|
||||
#endif
|
||||
|
||||
CHECK_MPI_OK( mp_invmod(&k, &n, &k) ); /* k = k**-1 mod n */
|
||||
CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) ); /* d = d * r mod n */
|
||||
CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) ); /* s = s + d mod n */
|
||||
CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) ); /* s = s * k mod n */
|
||||
|
||||
#if EC_DEBUG
|
||||
mp_todecimal(&s, mpstr);
|
||||
printf("s : %s (dec)\n", mpstr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 5
|
||||
**
|
||||
** verify s != 0
|
||||
*/
|
||||
if (mp_cmp_z(&s) == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Signature is tuple (r, s)
|
||||
*/
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, len) );
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + len, len) );
|
||||
signature->len = 2*len;
|
||||
|
||||
rv = SECSuccess;
|
||||
err = MP_OKAY;
|
||||
cleanup:
|
||||
mp_clear(&x1);
|
||||
mp_clear(&d);
|
||||
mp_clear(&k);
|
||||
mp_clear(&r);
|
||||
mp_clear(&s);
|
||||
mp_clear(&n);
|
||||
|
||||
if (kGpoint.data) {
|
||||
PORT_ZFree(kGpoint.data, 2*len + 1);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ECDSA signing with seed %s\n",
|
||||
(rv == SECSuccess) ? "succeeded" : "failed");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Computes the ECDSA signature on the digest using the given key
|
||||
** and a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
int prerr = 0;
|
||||
int n = (key->ecParams.fieldID.size + 7) >> 3;
|
||||
unsigned char mask = bitmask[n * 8 - key->ecParams.fieldID.size];
|
||||
unsigned char *kseed = NULL;
|
||||
|
||||
/* Generate random seed of appropriate size as dictated
|
||||
* by field size.
|
||||
*/
|
||||
if ((kseed = PORT_Alloc(n)) == NULL) return SECFailure;
|
||||
|
||||
do {
|
||||
if (RNG_GenerateGlobalRandomBytes(kseed, n) != SECSuccess)
|
||||
goto cleanup;
|
||||
*kseed &= mask;
|
||||
rv = ECDSA_SignDigestWithSeed(key, signature, digest, kseed, n);
|
||||
if (rv) prerr = PORT_GetError();
|
||||
} while ((rv != SECSuccess) && (prerr == SEC_ERROR_NEED_RANDOM));
|
||||
|
||||
cleanup:
|
||||
if (kseed) PORT_ZFree(kseed, n);
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ECDSA signing %s\n",
|
||||
(rv == SECSuccess) ? "succeeded" : "failed");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Checks the signature on the given digest using the key provided.
|
||||
*/
|
||||
SECStatus
|
||||
ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
|
||||
const SECItem *digest)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
mp_int r_, s_; /* tuple (r', s') is received signature) */
|
||||
mp_int c, u1, u2, v; /* intermediate values used in verification */
|
||||
mp_int x1, y1;
|
||||
mp_int x2, y2;
|
||||
mp_int n;
|
||||
mp_err err = MP_OKAY;
|
||||
PRArenaPool *arena = NULL;
|
||||
ECParams *ecParams = NULL;
|
||||
SECItem pointA = { siBuffer, NULL, 0 };
|
||||
SECItem pointB = { siBuffer, NULL, 0 };
|
||||
SECItem pointC = { siBuffer, NULL, 0 };
|
||||
int len;
|
||||
|
||||
#if EC_DEBUG
|
||||
char mpstr[256];
|
||||
printf("ECDSA verification called\n");
|
||||
#endif
|
||||
|
||||
/* Check args */
|
||||
if (!key || !signature || !digest ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ecParams = &(key->ecParams);
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
if (signature->len < 2*len) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Initialize an arena for pointA, pointB and pointC */
|
||||
if ((arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)) == NULL)
|
||||
goto cleanup;
|
||||
|
||||
SECITEM_AllocItem(arena, &pointA, 2*len + 1);
|
||||
SECITEM_AllocItem(arena, &pointB, 2*len + 1);
|
||||
SECITEM_AllocItem(arena, &pointC, 2*len + 1);
|
||||
if (pointA.data == NULL || pointB.data == NULL || pointC.data == NULL)
|
||||
goto cleanup;
|
||||
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&r_) = 0;
|
||||
MP_DIGITS(&s_) = 0;
|
||||
MP_DIGITS(&c) = 0;
|
||||
MP_DIGITS(&u1) = 0;
|
||||
MP_DIGITS(&u2) = 0;
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&y1) = 0;
|
||||
MP_DIGITS(&x2) = 0;
|
||||
MP_DIGITS(&y2) = 0;
|
||||
MP_DIGITS(&v) = 0;
|
||||
MP_DIGITS(&n) = 0;
|
||||
CHECK_MPI_OK( mp_init(&r_) );
|
||||
CHECK_MPI_OK( mp_init(&s_) );
|
||||
CHECK_MPI_OK( mp_init(&c) );
|
||||
CHECK_MPI_OK( mp_init(&u1) );
|
||||
CHECK_MPI_OK( mp_init(&u2) );
|
||||
CHECK_MPI_OK( mp_init(&x1) );
|
||||
CHECK_MPI_OK( mp_init(&y1) );
|
||||
CHECK_MPI_OK( mp_init(&x2) );
|
||||
CHECK_MPI_OK( mp_init(&y2) );
|
||||
CHECK_MPI_OK( mp_init(&v) );
|
||||
CHECK_MPI_OK( mp_init(&n) );
|
||||
|
||||
/*
|
||||
** Convert received signature (r', s') into MPI integers.
|
||||
*/
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, len) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + len, len) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.2, Steps 1 and 2
|
||||
**
|
||||
** Verify that 0 < r' < n and 0 < s' < n
|
||||
*/
|
||||
SECITEM_TO_MPINT(ecParams->order, &n);
|
||||
if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
|
||||
mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0)
|
||||
goto cleanup; /* will return rv == SECFailure */
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.2, Step 3
|
||||
**
|
||||
** c = (s')**-1 mod n
|
||||
*/
|
||||
CHECK_MPI_OK( mp_invmod(&s_, &n, &c) ); /* c = (s')**-1 mod n */
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.2, Step 4
|
||||
**
|
||||
** u1 = ((SHA1(M')) * c) mod n
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
|
||||
|
||||
#if EC_DEBUG
|
||||
mp_todecimal(&r_, mpstr);
|
||||
printf("r_: %s (dec)\n", mpstr);
|
||||
mp_todecimal(&s_, mpstr);
|
||||
printf("s_: %s (dec)\n", mpstr);
|
||||
mp_todecimal(&c, mpstr);
|
||||
printf("c : %s (dec)\n", mpstr);
|
||||
mp_todecimal(&u1, mpstr);
|
||||
printf("digest: %s (dec)\n", mpstr);
|
||||
#endif
|
||||
|
||||
CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) ); /* u1 = u1 * c mod n */
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.2, Step 4
|
||||
**
|
||||
** u2 = ((r') * c) mod n
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.3, Step 1
|
||||
**
|
||||
** Compute u1*G + u2*Q
|
||||
** Here, A = u1.G B = u2.Q and C = A + B
|
||||
** If the result, C, is the point at infinity, reject the signature
|
||||
*/
|
||||
if ((ec_point_mul(ecParams, &u1, &ecParams->base, &pointA)
|
||||
== SECFailure) ||
|
||||
(ec_point_mul(ecParams, &u2, &key->publicValue, &pointB)
|
||||
== SECFailure) ||
|
||||
(ec_point_add(ecParams, &pointA, &pointB, &pointC) == SECFailure) ||
|
||||
ec_point_at_infinity(&pointC)) {
|
||||
rv = SECFailure;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, len) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.4, Step 2
|
||||
**
|
||||
** v = x1 mod n
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mod(&x1, &n, &v) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.4, Step 3
|
||||
**
|
||||
** Verification: v == r'
|
||||
*/
|
||||
if (mp_cmp(&v, &r_)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
rv = SECFailure; /* Signature failed to verify. */
|
||||
} else {
|
||||
rv = SECSuccess; /* Signature verified. */
|
||||
}
|
||||
|
||||
#if EC_DEBUG
|
||||
mp_todecimal(&u1, mpstr);
|
||||
printf("u1: %s (dec)\n", mpstr);
|
||||
mp_todecimal(&u2, mpstr);
|
||||
printf("u2: %s (dec)\n", mpstr);
|
||||
mp_tohex(&x1, mpstr);
|
||||
printf("x1: %s\n", mpstr);
|
||||
mp_todecimal(&v, mpstr);
|
||||
printf("v : %s (dec)\n", mpstr);
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
mp_clear(&r_);
|
||||
mp_clear(&s_);
|
||||
mp_clear(&c);
|
||||
mp_clear(&u1);
|
||||
mp_clear(&u2);
|
||||
mp_clear(&x1);
|
||||
mp_clear(&y1);
|
||||
mp_clear(&x2);
|
||||
mp_clear(&y2);
|
||||
mp_clear(&v);
|
||||
mp_clear(&n);
|
||||
|
||||
if (arena) PORT_FreeArena(arena, PR_TRUE);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ECDSA verification %s\n",
|
||||
(rv == SECSuccess) ? "succeeded" : "failed");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Elliptic Curve Cryptography library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ec_h_
|
||||
#define __ec_h_
|
||||
|
||||
#define EC_DEBUG 0
|
||||
#define EC_POINT_FORM_COMPRESSED_Y0 0x02
|
||||
#define EC_POINT_FORM_COMPRESSED_Y1 0x03
|
||||
#define EC_POINT_FORM_UNCOMPRESSED 0x04
|
||||
#define EC_POINT_FORM_HYBRID_Y0 0x06
|
||||
#define EC_POINT_FORM_HYBRID_Y1 0x07
|
||||
|
||||
#define ANSI_X962_CURVE_OID_TOTAL_LEN 10
|
||||
#define SECG_CURVE_OID_TOTAL_LEN 7
|
||||
|
||||
#endif /* __ec_h_ */
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <plstr.h>
|
||||
#include "aglobal.h"
|
||||
#include "bsafe.h"
|
||||
#include "secport.h"
|
||||
|
||||
void CALL_CONV T_memset (p, c, count)
|
||||
POINTER p;
|
||||
int c;
|
||||
unsigned int count;
|
||||
{
|
||||
if (count >= 0)
|
||||
memset(p, c, count);
|
||||
}
|
||||
|
||||
void CALL_CONV T_memcpy (d, s, count)
|
||||
POINTER d, s;
|
||||
unsigned int count;
|
||||
{
|
||||
if (count >= 0)
|
||||
memcpy(d, s, count);
|
||||
}
|
||||
|
||||
void CALL_CONV T_memmove (d, s, count)
|
||||
POINTER d, s;
|
||||
unsigned int count;
|
||||
{
|
||||
if (count >= 0)
|
||||
PORT_Memmove(d, s, count);
|
||||
}
|
||||
|
||||
int CALL_CONV T_memcmp (s1, s2, count)
|
||||
POINTER s1, s2;
|
||||
unsigned int count;
|
||||
{
|
||||
if (count == 0)
|
||||
return (0);
|
||||
else
|
||||
return(memcmp(s1, s2, count));
|
||||
}
|
||||
|
||||
POINTER CALL_CONV T_malloc (size)
|
||||
unsigned int size;
|
||||
{
|
||||
return((POINTER)PORT_Alloc(size == 0 ? 1 : size));
|
||||
}
|
||||
|
||||
POINTER CALL_CONV T_realloc (p, size)
|
||||
POINTER p;
|
||||
unsigned int size;
|
||||
{
|
||||
POINTER result;
|
||||
|
||||
if (p == NULL_PTR)
|
||||
return (T_malloc(size));
|
||||
|
||||
if ((result = (POINTER)PORT_Realloc(p, size == 0 ? 1 : size)) == NULL_PTR)
|
||||
PORT_Free(p);
|
||||
return (result);
|
||||
}
|
||||
|
||||
void CALL_CONV T_free (p)
|
||||
POINTER p;
|
||||
{
|
||||
if (p != NULL_PTR)
|
||||
PORT_Free(p);
|
||||
}
|
||||
|
||||
unsigned int CALL_CONV T_strlen(p)
|
||||
char *p;
|
||||
{
|
||||
return PL_strlen(p);
|
||||
}
|
||||
|
||||
void CALL_CONV T_strcpy(dest, src)
|
||||
char *dest;
|
||||
char *src;
|
||||
{
|
||||
PL_strcpy(dest, src);
|
||||
}
|
||||
|
||||
int CALL_CONV T_strcmp (a, b)
|
||||
char *a, *b;
|
||||
{
|
||||
return (PL_strcmp (a, b));
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* ldvector.c - platform dependent DSO containing freebl implementation.
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: ldvector.c,v 1.6 2003-02-27 01:31:13 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "loader.h"
|
||||
|
||||
static const struct FREEBLVectorStr vector = {
|
||||
|
||||
sizeof vector,
|
||||
FREEBL_VERSION,
|
||||
|
||||
RSA_NewKey,
|
||||
RSA_PublicKeyOp,
|
||||
RSA_PrivateKeyOp,
|
||||
DSA_NewKey,
|
||||
DSA_SignDigest,
|
||||
DSA_VerifyDigest,
|
||||
DSA_NewKeyFromSeed,
|
||||
DSA_SignDigestWithSeed,
|
||||
DH_GenParam,
|
||||
DH_NewKey,
|
||||
DH_Derive,
|
||||
KEA_Derive,
|
||||
KEA_Verify,
|
||||
RC4_CreateContext,
|
||||
RC4_DestroyContext,
|
||||
RC4_Encrypt,
|
||||
RC4_Decrypt,
|
||||
RC2_CreateContext,
|
||||
RC2_DestroyContext,
|
||||
RC2_Encrypt,
|
||||
RC2_Decrypt,
|
||||
RC5_CreateContext,
|
||||
RC5_DestroyContext,
|
||||
RC5_Encrypt,
|
||||
RC5_Decrypt,
|
||||
DES_CreateContext,
|
||||
DES_DestroyContext,
|
||||
DES_Encrypt,
|
||||
DES_Decrypt,
|
||||
AES_CreateContext,
|
||||
AES_DestroyContext,
|
||||
AES_Encrypt,
|
||||
AES_Decrypt,
|
||||
MD5_Hash,
|
||||
MD5_HashBuf,
|
||||
MD5_NewContext,
|
||||
MD5_DestroyContext,
|
||||
MD5_Begin,
|
||||
MD5_Update,
|
||||
MD5_End,
|
||||
MD5_FlattenSize,
|
||||
MD5_Flatten,
|
||||
MD5_Resurrect,
|
||||
MD5_TraceState,
|
||||
MD2_Hash,
|
||||
MD2_NewContext,
|
||||
MD2_DestroyContext,
|
||||
MD2_Begin,
|
||||
MD2_Update,
|
||||
MD2_End,
|
||||
MD2_FlattenSize,
|
||||
MD2_Flatten,
|
||||
MD2_Resurrect,
|
||||
SHA1_Hash,
|
||||
SHA1_HashBuf,
|
||||
SHA1_NewContext,
|
||||
SHA1_DestroyContext,
|
||||
SHA1_Begin,
|
||||
SHA1_Update,
|
||||
SHA1_End,
|
||||
SHA1_TraceState,
|
||||
SHA1_FlattenSize,
|
||||
SHA1_Flatten,
|
||||
SHA1_Resurrect,
|
||||
RNG_RNGInit,
|
||||
RNG_RandomUpdate,
|
||||
RNG_GenerateGlobalRandomBytes,
|
||||
RNG_RNGShutdown,
|
||||
PQG_ParamGen,
|
||||
PQG_ParamGenSeedLen,
|
||||
PQG_VerifyParams,
|
||||
|
||||
/* End of Version 3.001. */
|
||||
|
||||
RSA_PrivateKeyOpDoubleChecked,
|
||||
RSA_PrivateKeyCheck,
|
||||
BL_Cleanup,
|
||||
|
||||
/* End of Version 3.002. */
|
||||
|
||||
SHA256_NewContext,
|
||||
SHA256_DestroyContext,
|
||||
SHA256_Begin,
|
||||
SHA256_Update,
|
||||
SHA256_End,
|
||||
SHA256_HashBuf,
|
||||
SHA256_Hash,
|
||||
SHA256_TraceState,
|
||||
SHA256_FlattenSize,
|
||||
SHA256_Flatten,
|
||||
SHA256_Resurrect,
|
||||
|
||||
SHA512_NewContext,
|
||||
SHA512_DestroyContext,
|
||||
SHA512_Begin,
|
||||
SHA512_Update,
|
||||
SHA512_End,
|
||||
SHA512_HashBuf,
|
||||
SHA512_Hash,
|
||||
SHA512_TraceState,
|
||||
SHA512_FlattenSize,
|
||||
SHA512_Flatten,
|
||||
SHA512_Resurrect,
|
||||
|
||||
SHA384_NewContext,
|
||||
SHA384_DestroyContext,
|
||||
SHA384_Begin,
|
||||
SHA384_Update,
|
||||
SHA384_End,
|
||||
SHA384_HashBuf,
|
||||
SHA384_Hash,
|
||||
SHA384_TraceState,
|
||||
SHA384_FlattenSize,
|
||||
SHA384_Flatten,
|
||||
SHA384_Resurrect,
|
||||
|
||||
/* End of Version 3.003. */
|
||||
|
||||
AESKeyWrap_CreateContext,
|
||||
AESKeyWrap_DestroyContext,
|
||||
AESKeyWrap_Encrypt,
|
||||
AESKeyWrap_Decrypt,
|
||||
|
||||
/* End of Version 3.004. */
|
||||
|
||||
BLAPI_SHVerify,
|
||||
BLAPI_VerifySelf,
|
||||
|
||||
/* End of Version 3.005. */
|
||||
|
||||
EC_NewKey,
|
||||
EC_NewKeyFromSeed,
|
||||
EC_ValidatePublicKey,
|
||||
ECDH_Derive,
|
||||
ECDSA_SignDigest,
|
||||
ECDSA_VerifyDigest,
|
||||
ECDSA_SignDigestWithSeed,
|
||||
|
||||
/* End of Version 3.006. */
|
||||
};
|
||||
|
||||
|
||||
const FREEBLVector *
|
||||
FREEBL_GetVector(void)
|
||||
{
|
||||
return &vector;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,386 +0,0 @@
|
||||
/*
|
||||
* loader.h - load platform dependent DSO containing freebl implementation.
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: loader.h,v 1.9 2003-02-27 01:31:14 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _LOADER_H_
|
||||
#define _LOADER_H_ 1
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
#define FREEBL_VERSION 0x0306
|
||||
|
||||
struct FREEBLVectorStr {
|
||||
|
||||
unsigned short length; /* of this struct in bytes */
|
||||
unsigned short version; /* of this struct. */
|
||||
|
||||
RSAPrivateKey * (* p_RSA_NewKey)(int keySizeInBits,
|
||||
SECItem * publicExponent);
|
||||
|
||||
SECStatus (* p_RSA_PublicKeyOp) (RSAPublicKey * key,
|
||||
unsigned char * output,
|
||||
const unsigned char * input);
|
||||
|
||||
SECStatus (* p_RSA_PrivateKeyOp)(RSAPrivateKey * key,
|
||||
unsigned char * output,
|
||||
const unsigned char * input);
|
||||
|
||||
SECStatus (* p_DSA_NewKey)(const PQGParams * params,
|
||||
DSAPrivateKey ** privKey);
|
||||
|
||||
SECStatus (* p_DSA_SignDigest)(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_DSA_VerifyDigest)(DSAPublicKey * key,
|
||||
const SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_DSA_NewKeyFromSeed)(const PQGParams *params,
|
||||
const unsigned char * seed,
|
||||
DSAPrivateKey **privKey);
|
||||
|
||||
SECStatus (* p_DSA_SignDigestWithSeed)(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed);
|
||||
|
||||
SECStatus (* p_DH_GenParam)(int primeLen, DHParams ** params);
|
||||
|
||||
SECStatus (* p_DH_NewKey)(DHParams * params,
|
||||
DHPrivateKey ** privKey);
|
||||
|
||||
SECStatus (* p_DH_Derive)(SECItem * publicValue,
|
||||
SECItem * prime,
|
||||
SECItem * privateValue,
|
||||
SECItem * derivedSecret,
|
||||
unsigned int maxOutBytes);
|
||||
|
||||
SECStatus (* p_KEA_Derive)(SECItem *prime,
|
||||
SECItem *public1,
|
||||
SECItem *public2,
|
||||
SECItem *private1,
|
||||
SECItem *private2,
|
||||
SECItem *derivedSecret);
|
||||
|
||||
PRBool (* p_KEA_Verify)(SECItem *Y, SECItem *prime, SECItem *subPrime);
|
||||
|
||||
RC4Context * (* p_RC4_CreateContext)(const unsigned char *key, int len);
|
||||
|
||||
void (* p_RC4_DestroyContext)(RC4Context *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_RC4_Encrypt)(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_RC4_Decrypt)(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
RC2Context * (* p_RC2_CreateContext)(const unsigned char *key,
|
||||
unsigned int len, const unsigned char *iv,
|
||||
int mode, unsigned effectiveKeyLen);
|
||||
|
||||
void (* p_RC2_DestroyContext)(RC2Context *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_RC2_Encrypt)(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_RC2_Decrypt)(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
RC5Context *(* p_RC5_CreateContext)(const SECItem *key, unsigned int rounds,
|
||||
unsigned int wordSize, const unsigned char *iv, int mode);
|
||||
|
||||
void (* p_RC5_DestroyContext)(RC5Context *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_RC5_Encrypt)(RC5Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_RC5_Decrypt)(RC5Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
DESContext *(* p_DES_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int mode, PRBool encrypt);
|
||||
|
||||
void (* p_DES_DestroyContext)(DESContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_DES_Encrypt)(DESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_DES_Decrypt)(DESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
AESContext * (* p_AES_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int mode, int encrypt, unsigned int keylen,
|
||||
unsigned int blocklen);
|
||||
|
||||
void (* p_AES_DestroyContext)(AESContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_AES_Encrypt)(AESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_AES_Decrypt)(AESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_MD5_Hash)(unsigned char *dest, const char *src);
|
||||
|
||||
SECStatus (* p_MD5_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
|
||||
MD5Context *(* p_MD5_NewContext)(void);
|
||||
|
||||
void (* p_MD5_DestroyContext)(MD5Context *cx, PRBool freeit);
|
||||
|
||||
void (* p_MD5_Begin)(MD5Context *cx);
|
||||
|
||||
void (* p_MD5_Update)(MD5Context *cx,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
void (* p_MD5_End)(MD5Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
|
||||
unsigned int (* p_MD5_FlattenSize)(MD5Context *cx);
|
||||
|
||||
SECStatus (* p_MD5_Flatten)(MD5Context *cx,unsigned char *space);
|
||||
|
||||
MD5Context * (* p_MD5_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
void (* p_MD5_TraceState)(MD5Context *cx);
|
||||
|
||||
SECStatus (* p_MD2_Hash)(unsigned char *dest, const char *src);
|
||||
|
||||
MD2Context *(* p_MD2_NewContext)(void);
|
||||
|
||||
void (* p_MD2_DestroyContext)(MD2Context *cx, PRBool freeit);
|
||||
|
||||
void (* p_MD2_Begin)(MD2Context *cx);
|
||||
|
||||
void (* p_MD2_Update)(MD2Context *cx,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
void (* p_MD2_End)(MD2Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
|
||||
unsigned int (* p_MD2_FlattenSize)(MD2Context *cx);
|
||||
|
||||
SECStatus (* p_MD2_Flatten)(MD2Context *cx,unsigned char *space);
|
||||
|
||||
MD2Context * (* p_MD2_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SECStatus (* p_SHA1_Hash)(unsigned char *dest, const char *src);
|
||||
|
||||
SECStatus (* p_SHA1_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
|
||||
SHA1Context *(* p_SHA1_NewContext)(void);
|
||||
|
||||
void (* p_SHA1_DestroyContext)(SHA1Context *cx, PRBool freeit);
|
||||
|
||||
void (* p_SHA1_Begin)(SHA1Context *cx);
|
||||
|
||||
void (* p_SHA1_Update)(SHA1Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
|
||||
void (* p_SHA1_End)(SHA1Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
|
||||
void (* p_SHA1_TraceState)(SHA1Context *cx);
|
||||
|
||||
unsigned int (* p_SHA1_FlattenSize)(SHA1Context *cx);
|
||||
|
||||
SECStatus (* p_SHA1_Flatten)(SHA1Context *cx,unsigned char *space);
|
||||
|
||||
SHA1Context * (* p_SHA1_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SECStatus (* p_RNG_RNGInit)(void);
|
||||
|
||||
SECStatus (* p_RNG_RandomUpdate)(const void *data, size_t bytes);
|
||||
|
||||
SECStatus (* p_RNG_GenerateGlobalRandomBytes)(void *dest, size_t len);
|
||||
|
||||
void (* p_RNG_RNGShutdown)(void);
|
||||
|
||||
SECStatus (* p_PQG_ParamGen)(unsigned int j, PQGParams **pParams,
|
||||
PQGVerify **pVfy);
|
||||
|
||||
SECStatus (* p_PQG_ParamGenSeedLen)( unsigned int j, unsigned int seedBytes,
|
||||
PQGParams **pParams, PQGVerify **pVfy);
|
||||
|
||||
SECStatus (* p_PQG_VerifyParams)(const PQGParams *params,
|
||||
const PQGVerify *vfy, SECStatus *result);
|
||||
|
||||
/* Version 3.001 came to here */
|
||||
|
||||
SECStatus (* p_RSA_PrivateKeyOpDoubleChecked)(RSAPrivateKey *key,
|
||||
unsigned char *output,
|
||||
const unsigned char *input);
|
||||
|
||||
SECStatus (* p_RSA_PrivateKeyCheck)(RSAPrivateKey *key);
|
||||
|
||||
void (* p_BL_Cleanup)(void);
|
||||
|
||||
/* Version 3.002 came to here */
|
||||
|
||||
SHA256Context *(* p_SHA256_NewContext)(void);
|
||||
void (* p_SHA256_DestroyContext)(SHA256Context *cx, PRBool freeit);
|
||||
void (* p_SHA256_Begin)(SHA256Context *cx);
|
||||
void (* p_SHA256_Update)(SHA256Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
void (* p_SHA256_End)(SHA256Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
SECStatus (* p_SHA256_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
SECStatus (* p_SHA256_Hash)(unsigned char *dest, const char *src);
|
||||
void (* p_SHA256_TraceState)(SHA256Context *cx);
|
||||
unsigned int (* p_SHA256_FlattenSize)(SHA256Context *cx);
|
||||
SECStatus (* p_SHA256_Flatten)(SHA256Context *cx,unsigned char *space);
|
||||
SHA256Context * (* p_SHA256_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SHA512Context *(* p_SHA512_NewContext)(void);
|
||||
void (* p_SHA512_DestroyContext)(SHA512Context *cx, PRBool freeit);
|
||||
void (* p_SHA512_Begin)(SHA512Context *cx);
|
||||
void (* p_SHA512_Update)(SHA512Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
void (* p_SHA512_End)(SHA512Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
SECStatus (* p_SHA512_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
SECStatus (* p_SHA512_Hash)(unsigned char *dest, const char *src);
|
||||
void (* p_SHA512_TraceState)(SHA512Context *cx);
|
||||
unsigned int (* p_SHA512_FlattenSize)(SHA512Context *cx);
|
||||
SECStatus (* p_SHA512_Flatten)(SHA512Context *cx,unsigned char *space);
|
||||
SHA512Context * (* p_SHA512_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SHA384Context *(* p_SHA384_NewContext)(void);
|
||||
void (* p_SHA384_DestroyContext)(SHA384Context *cx, PRBool freeit);
|
||||
void (* p_SHA384_Begin)(SHA384Context *cx);
|
||||
void (* p_SHA384_Update)(SHA384Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
void (* p_SHA384_End)(SHA384Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
SECStatus (* p_SHA384_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
SECStatus (* p_SHA384_Hash)(unsigned char *dest, const char *src);
|
||||
void (* p_SHA384_TraceState)(SHA384Context *cx);
|
||||
unsigned int (* p_SHA384_FlattenSize)(SHA384Context *cx);
|
||||
SECStatus (* p_SHA384_Flatten)(SHA384Context *cx,unsigned char *space);
|
||||
SHA384Context * (* p_SHA384_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
/* Version 3.003 came to here */
|
||||
|
||||
AESKeyWrapContext * (* p_AESKeyWrap_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv, int encrypt, unsigned int keylen);
|
||||
|
||||
void (* p_AESKeyWrap_DestroyContext)(AESKeyWrapContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_AESKeyWrap_Encrypt)(AESKeyWrapContext *cx,
|
||||
unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_AESKeyWrap_Decrypt)(AESKeyWrapContext *cx,
|
||||
unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
/* Version 3.004 came to here */
|
||||
|
||||
PRBool (*p_BLAPI_SHVerify)(const char *name, PRFuncPtr addr);
|
||||
PRBool (*p_BLAPI_VerifySelf)(const char *name);
|
||||
|
||||
/* Version 3.005 came to here */
|
||||
|
||||
SECStatus (* p_EC_NewKey)(ECParams * params,
|
||||
ECPrivateKey ** privKey);
|
||||
|
||||
SECStatus (* p_EC_NewKeyFromSeed)(ECParams * params,
|
||||
ECPrivateKey ** privKey,
|
||||
const unsigned char * seed,
|
||||
int seedlen);
|
||||
|
||||
SECStatus (* p_EC_ValidatePublicKey)(ECParams * params,
|
||||
SECItem * publicValue);
|
||||
|
||||
SECStatus (* p_ECDH_Derive)(SECItem * publicValue,
|
||||
ECParams * params,
|
||||
SECItem * privateValue,
|
||||
PRBool withCofactor,
|
||||
SECItem * derivedSecret);
|
||||
|
||||
SECStatus (* p_ECDSA_SignDigest)(ECPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_ECDSA_VerifyDigest)(ECPublicKey * key,
|
||||
const SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_ECDSA_SignDigestWithSeed)(ECPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed,
|
||||
const int seedlen);
|
||||
|
||||
/* Version 3.006 came to here */
|
||||
|
||||
};
|
||||
|
||||
typedef struct FREEBLVectorStr FREEBLVector;
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
typedef const FREEBLVector * FREEBLGetVectorFn(void);
|
||||
|
||||
extern FREEBLGetVectorFn FREEBL_GetVector;
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
@@ -1,315 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#ifdef notdef
|
||||
#include "xp_core.h"
|
||||
#include "xp_file.h"
|
||||
#endif
|
||||
#include "secrng.h"
|
||||
#include "mcom_db.h"
|
||||
#ifdef XP_MAC
|
||||
#include <Events.h>
|
||||
#include <OSUtils.h>
|
||||
#include <QDOffscreen.h>
|
||||
#include <PPCToolbox.h>
|
||||
#include <Processes.h>
|
||||
#include <LowMem.h>
|
||||
#include <Scrap.h>
|
||||
|
||||
/* Static prototypes */
|
||||
static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen);
|
||||
void FE_ReadScreen();
|
||||
|
||||
static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen)
|
||||
{
|
||||
union endianness {
|
||||
int32 i;
|
||||
char c[4];
|
||||
} u;
|
||||
|
||||
if (srclen <= dstlen) {
|
||||
memcpy(dst, src, srclen);
|
||||
return srclen;
|
||||
}
|
||||
u.i = 0x01020304;
|
||||
if (u.c[0] == 0x01) {
|
||||
/* big-endian case */
|
||||
memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
|
||||
} else {
|
||||
/* little-endian case */
|
||||
memcpy(dst, src, dstlen);
|
||||
}
|
||||
return dstlen;
|
||||
}
|
||||
|
||||
size_t RNG_GetNoise(void *buf, size_t maxbytes)
|
||||
{
|
||||
UnsignedWide microTickCount;
|
||||
Microseconds(µTickCount);
|
||||
return CopyLowBits(buf, maxbytes, µTickCount, sizeof(microTickCount));
|
||||
}
|
||||
|
||||
void RNG_FileForRNG(const char *filename)
|
||||
{
|
||||
unsigned char buffer[BUFSIZ];
|
||||
size_t bytes;
|
||||
#ifdef notdef /*sigh*/
|
||||
XP_File file;
|
||||
unsigned long totalFileBytes = 0;
|
||||
|
||||
if (filename == NULL) /* For now, read in global history if filename is null */
|
||||
file = XP_FileOpen(NULL, xpGlobalHistory,XP_FILE_READ_BIN);
|
||||
else
|
||||
file = XP_FileOpen(NULL, xpURL,XP_FILE_READ_BIN);
|
||||
if (file != NULL) {
|
||||
for (;;) {
|
||||
bytes = XP_FileRead(buffer, sizeof(buffer), file);
|
||||
if (bytes == 0) break;
|
||||
RNG_RandomUpdate( buffer, bytes);
|
||||
totalFileBytes += bytes;
|
||||
if (totalFileBytes > 100*1024) break; /* No more than 100 K */
|
||||
}
|
||||
XP_FileClose(file);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Pass yet another snapshot of our highest resolution clock into
|
||||
* the hash function.
|
||||
*/
|
||||
bytes = RNG_GetNoise(buffer, sizeof(buffer));
|
||||
RNG_RandomUpdate(buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
void RNG_SystemInfoForRNG()
|
||||
{
|
||||
/* Time */
|
||||
{
|
||||
unsigned long sec;
|
||||
size_t bytes;
|
||||
GetDateTime(&sec); /* Current time since 1970 */
|
||||
RNG_RandomUpdate( &sec, sizeof(sec));
|
||||
bytes = RNG_GetNoise(&sec, sizeof(sec));
|
||||
RNG_RandomUpdate(&sec, bytes);
|
||||
}
|
||||
/* User specific variables */
|
||||
{
|
||||
MachineLocation loc;
|
||||
ReadLocation(&loc);
|
||||
RNG_RandomUpdate( &loc, sizeof(loc));
|
||||
}
|
||||
#if !TARGET_CARBON
|
||||
/* User name */
|
||||
{
|
||||
unsigned long userRef;
|
||||
Str32 userName;
|
||||
GetDefaultUser(&userRef, userName);
|
||||
RNG_RandomUpdate( &userRef, sizeof(userRef));
|
||||
RNG_RandomUpdate( userName, sizeof(userName));
|
||||
}
|
||||
#endif
|
||||
/* Mouse location */
|
||||
{
|
||||
Point mouseLoc;
|
||||
GetMouse(&mouseLoc);
|
||||
RNG_RandomUpdate( &mouseLoc, sizeof(mouseLoc));
|
||||
}
|
||||
/* Keyboard time threshold */
|
||||
{
|
||||
SInt16 keyTresh = LMGetKeyThresh();
|
||||
RNG_RandomUpdate( &keyTresh, sizeof(keyTresh));
|
||||
}
|
||||
/* Last key pressed */
|
||||
{
|
||||
SInt8 keyLast;
|
||||
keyLast = LMGetKbdLast();
|
||||
RNG_RandomUpdate( &keyLast, sizeof(keyLast));
|
||||
}
|
||||
/* Volume */
|
||||
{
|
||||
UInt8 volume = LMGetSdVolume();
|
||||
RNG_RandomUpdate( &volume, sizeof(volume));
|
||||
}
|
||||
#if !TARGET_CARBON
|
||||
/* Current directory */
|
||||
{
|
||||
SInt32 dir = LMGetCurDirStore();
|
||||
RNG_RandomUpdate( &dir, sizeof(dir));
|
||||
}
|
||||
#endif
|
||||
/* Process information about all the processes in the machine */
|
||||
{
|
||||
ProcessSerialNumber process;
|
||||
ProcessInfoRec pi;
|
||||
|
||||
process.highLongOfPSN = process.lowLongOfPSN = kNoProcess;
|
||||
|
||||
while (GetNextProcess(&process) == noErr)
|
||||
{
|
||||
FSSpec fileSpec;
|
||||
pi.processInfoLength = sizeof(ProcessInfoRec);
|
||||
pi.processName = NULL;
|
||||
pi.processAppSpec = &fileSpec;
|
||||
GetProcessInformation(&process, &pi);
|
||||
RNG_RandomUpdate( &pi, sizeof(pi));
|
||||
RNG_RandomUpdate( &fileSpec, sizeof(fileSpec));
|
||||
}
|
||||
}
|
||||
|
||||
#if !TARGET_CARBON
|
||||
/* Heap */
|
||||
{
|
||||
THz zone = LMGetTheZone();
|
||||
RNG_RandomUpdate( &zone, sizeof(zone));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Screen */
|
||||
{
|
||||
GDHandle h = GetMainDevice(); /* GDHandle is **GDevice */
|
||||
RNG_RandomUpdate( *h, sizeof(GDevice));
|
||||
}
|
||||
|
||||
#if !TARGET_CARBON
|
||||
/* Scrap size */
|
||||
{
|
||||
SInt32 scrapSize = LMGetScrapSize();
|
||||
RNG_RandomUpdate( &scrapSize, sizeof(scrapSize));
|
||||
}
|
||||
/* Scrap count */
|
||||
{
|
||||
SInt16 scrapCount = LMGetScrapCount();
|
||||
RNG_RandomUpdate( &scrapCount, sizeof(scrapCount));
|
||||
}
|
||||
#else
|
||||
{
|
||||
ScrapRef scrap;
|
||||
if (GetCurrentScrap(&scrap) == noErr) {
|
||||
UInt32 flavorCount;
|
||||
if (GetScrapFlavorCount(scrap, &flavorCount) == noErr) {
|
||||
ScrapFlavorInfo* flavorInfo = (ScrapFlavorInfo*) malloc(flavorCount * sizeof(ScrapFlavorInfo));
|
||||
if (flavorInfo != NULL) {
|
||||
if (GetScrapFlavorInfoList(scrap, &flavorCount, flavorInfo) == noErr) {
|
||||
UInt32 i;
|
||||
RNG_RandomUpdate(&flavorCount, sizeof(flavorCount));
|
||||
for (i = 0; i < flavorCount; ++i) {
|
||||
Size flavorSize;
|
||||
if (GetScrapFlavorSize(scrap, flavorInfo[i].flavorType, &flavorSize) == noErr)
|
||||
RNG_RandomUpdate(&flavorSize, sizeof(flavorSize));
|
||||
}
|
||||
}
|
||||
free(flavorInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* File stuff, last modified, etc. */
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
GetVolParmsInfoBuffer volInfo;
|
||||
pb.ioParam.ioVRefNum = 0;
|
||||
pb.ioParam.ioNamePtr = nil;
|
||||
pb.ioParam.ioBuffer = (Ptr) &volInfo;
|
||||
pb.ioParam.ioReqCount = sizeof(volInfo);
|
||||
PBHGetVolParmsSync(&pb);
|
||||
RNG_RandomUpdate( &volInfo, sizeof(volInfo));
|
||||
}
|
||||
#if !TARGET_CARBON
|
||||
/* Event queue */
|
||||
{
|
||||
EvQElPtr eventQ;
|
||||
for (eventQ = (EvQElPtr) LMGetEventQueue()->qHead;
|
||||
eventQ;
|
||||
eventQ = (EvQElPtr)eventQ->qLink)
|
||||
RNG_RandomUpdate( &eventQ->evtQWhat, sizeof(EventRecord));
|
||||
}
|
||||
#endif
|
||||
FE_ReadScreen();
|
||||
RNG_FileForRNG(NULL);
|
||||
}
|
||||
|
||||
void FE_ReadScreen()
|
||||
{
|
||||
UInt16 coords[4];
|
||||
PixMapHandle pmap;
|
||||
GDHandle gh;
|
||||
UInt16 screenHeight;
|
||||
UInt16 screenWidth; /* just what they say */
|
||||
UInt32 bytesToRead; /* number of bytes we're giving */
|
||||
UInt32 offset; /* offset into the graphics buffer */
|
||||
UInt16 rowBytes;
|
||||
UInt32 rowsToRead;
|
||||
float bytesPerPixel; /* dependent on buffer depth */
|
||||
Ptr p; /* temporary */
|
||||
UInt16 x, y, w, h;
|
||||
|
||||
gh = LMGetMainDevice();
|
||||
if ( !gh )
|
||||
return;
|
||||
pmap = (**gh).gdPMap;
|
||||
if ( !pmap )
|
||||
return;
|
||||
|
||||
RNG_GenerateGlobalRandomBytes( coords, sizeof( coords ) );
|
||||
|
||||
/* make x and y inside the screen rect */
|
||||
screenHeight = (**pmap).bounds.bottom - (**pmap).bounds.top;
|
||||
screenWidth = (**pmap).bounds.right - (**pmap).bounds.left;
|
||||
x = coords[0] % screenWidth;
|
||||
y = coords[1] % screenHeight;
|
||||
w = ( coords[2] & 0x7F ) | 0x40; /* Make sure that w is in the range 64..128 */
|
||||
h = ( coords[3] & 0x7F ) | 0x40; /* same for h */
|
||||
|
||||
bytesPerPixel = (**pmap).pixelSize / 8;
|
||||
rowBytes = (**pmap).rowBytes & 0x7FFF;
|
||||
|
||||
/* starting address */
|
||||
offset = ( rowBytes * y ) + (UInt32)( (float)x * bytesPerPixel );
|
||||
|
||||
/* don't read past the end of the pixmap's rowbytes */
|
||||
bytesToRead = PR_MIN( (UInt32)( w * bytesPerPixel ),
|
||||
(UInt32)( rowBytes - ( x * bytesPerPixel ) ) );
|
||||
|
||||
/* don't read past the end of the graphics device pixmap */
|
||||
rowsToRead = PR_MIN( h,
|
||||
( screenHeight - y ) );
|
||||
|
||||
p = GetPixBaseAddr( pmap ) + offset;
|
||||
|
||||
while ( rowsToRead-- )
|
||||
{
|
||||
RNG_RandomUpdate( p, bytesToRead );
|
||||
p += rowBytes;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,146 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
# Sun Microsystems, Inc. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = nss
|
||||
|
||||
ifndef FREEBL_RECURSIVE_BUILD
|
||||
LIBRARY_NAME = freebl
|
||||
else
|
||||
ifdef USE_PURE_32
|
||||
CORE_DEPTH = ../../../..
|
||||
LIBRARY_NAME = freebl_pure32
|
||||
else
|
||||
LIBRARY_NAME = freebl_hybrid
|
||||
endif
|
||||
endif
|
||||
|
||||
# same version as rest of freebl
|
||||
LIBRARY_VERSION = _3
|
||||
|
||||
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
|
||||
|
||||
REQUIRES =
|
||||
|
||||
EXPORTS = \
|
||||
blapi.h \
|
||||
blapit.h \
|
||||
secrng.h \
|
||||
shsign.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
secmpi.h \
|
||||
ec.h \
|
||||
$(NULL)
|
||||
|
||||
MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
|
||||
MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c
|
||||
|
||||
ifdef MOZILLA_BSAFE_BUILD
|
||||
CSRCS = \
|
||||
fblstdlib.c \
|
||||
sha_fast.c \
|
||||
md2.c \
|
||||
md5.c \
|
||||
blapi_bsf.c \
|
||||
$(MPI_SRCS) \
|
||||
dh.c \
|
||||
$(NULL)
|
||||
else
|
||||
CSRCS = \
|
||||
ldvector.c \
|
||||
prng_fips1861.c \
|
||||
sysrand.c \
|
||||
sha_fast.c \
|
||||
md2.c \
|
||||
md5.c \
|
||||
sha512.c \
|
||||
alg2268.c \
|
||||
arcfour.c \
|
||||
arcfive.c \
|
||||
desblapi.c \
|
||||
des.c \
|
||||
rijndael.c \
|
||||
aeskeywrap.c \
|
||||
dh.c \
|
||||
ec.c \
|
||||
GFp_ecl.c \
|
||||
GF2m_ecl.c \
|
||||
pqg.c \
|
||||
dsa.c \
|
||||
rsa.c \
|
||||
shvfy.c \
|
||||
$(MPI_SRCS) \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ALL_CSRCS := $(CSRCS)
|
||||
|
||||
ALL_HDRS = \
|
||||
blapi.h \
|
||||
blapit.h \
|
||||
des.h \
|
||||
ec.h \
|
||||
GFp_ecl.h \
|
||||
GF2m_ecl.h \
|
||||
loader.h \
|
||||
rijndael.h \
|
||||
secmpi.h \
|
||||
sha.h \
|
||||
sha_fast.h \
|
||||
shsign.h \
|
||||
vis_proto.h \
|
||||
$(NULL)
|
||||
|
||||
ifdef AES_GEN_TBL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES
|
||||
else
|
||||
ifdef AES_GEN_TBL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES_MACRO
|
||||
else
|
||||
ifdef AES_GEN_VAL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES
|
||||
else
|
||||
ifdef AES_GEN_VAL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES_MACRO
|
||||
else
|
||||
DEFINES += -DRIJNDAEL_INCLUDE_TABLES
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -1,39 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
libfreebl_3.so {
|
||||
global:
|
||||
FREEBL_GetVector;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
BIN
mozilla/webtools/tinderbox/1afi003r.gif
Normal file
BIN
mozilla/webtools/tinderbox/1afi003r.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
216
mozilla/webtools/tinderbox/Backwards.pm
Normal file
216
mozilla/webtools/tinderbox/Backwards.pm
Normal file
@@ -0,0 +1,216 @@
|
||||
# Backwards.pm
|
||||
|
||||
# Copyright (C) 1999 Uri Guttman. All rights reserved.
|
||||
# mail bugs, comments and feedback to uri@sysarch.com
|
||||
|
||||
|
||||
use strict ;
|
||||
|
||||
package Backwards ;
|
||||
|
||||
use Symbol ;
|
||||
use Fcntl ;
|
||||
use Carp ;
|
||||
use integer ;
|
||||
|
||||
#my $max_read_size = 3 ;
|
||||
|
||||
my $max_read_size = 1 << 13 ;
|
||||
|
||||
# support tied handles. the tied calls map directly to the object methods
|
||||
|
||||
*TIEHANDLE = \&new ;
|
||||
*READLINE = \&readline ;
|
||||
|
||||
# create a new Backwards object
|
||||
|
||||
sub new {
|
||||
|
||||
my( $class, $filename ) = @_ ;
|
||||
|
||||
my( $handle, $seek_pos, $read_size, $self ) ;
|
||||
|
||||
# get a new handle symbol and the real file handle
|
||||
|
||||
$handle = gensym() ;
|
||||
|
||||
# open the file for reading
|
||||
|
||||
unless( sysopen( $handle, $filename, O_RDONLY ) ) {
|
||||
carp "Can't open $filename $!" ;
|
||||
return ;
|
||||
}
|
||||
|
||||
# seek to the end of the file
|
||||
|
||||
seek( $handle, 0, 2 ) ;
|
||||
$seek_pos = tell( $handle ) ;
|
||||
|
||||
# get the size of the first block to read,
|
||||
# either a trailing partial one (the % size) or full sized one (max read size)
|
||||
|
||||
$read_size = $seek_pos % $max_read_size || $max_read_size ;
|
||||
|
||||
# create the hash for the object, bless and return it
|
||||
|
||||
$self = {
|
||||
'file_name' => $filename,
|
||||
'handle' => $handle,
|
||||
'read_size' => $read_size,
|
||||
'seek_pos' => $seek_pos,
|
||||
'lines' => [],
|
||||
} ;
|
||||
|
||||
return( bless( $self, $class ) ) ;
|
||||
}
|
||||
|
||||
sub readline {
|
||||
|
||||
my( $self, $line_ref ) = @_ ;
|
||||
|
||||
my( $handle, $lines_ref, $seek_pos, $read_cnt, $read_buf,
|
||||
$file_size, $read_size, $text ) ;
|
||||
|
||||
# get the buffer of lines
|
||||
|
||||
$lines_ref = $self->{'lines'} ;
|
||||
|
||||
while( 1 ) {
|
||||
|
||||
# see if there is more than 1 line in the buffer
|
||||
|
||||
if ( @{$lines_ref} > 1 ) {
|
||||
|
||||
# we have a complete line so return it
|
||||
|
||||
return( pop @{$lines_ref} ) ;
|
||||
}
|
||||
|
||||
# we don't have a complete, so have to read blocks until we do
|
||||
|
||||
$seek_pos = $self->{'seek_pos'} ;
|
||||
|
||||
# see if we are at the beginning of the file
|
||||
|
||||
if ( $seek_pos == 0 ) {
|
||||
|
||||
# the last read never made more lines, so return the last line in the buffer
|
||||
# if no lines left then undef will be returned
|
||||
|
||||
return( pop @{$lines_ref} ) ;
|
||||
}
|
||||
|
||||
#print "c size $read_size\n" ;
|
||||
|
||||
# we have to read more text so get the handle and the current read size
|
||||
|
||||
$handle = $self->{'handle'} ;
|
||||
$read_size = $self->{'read_size'} ;
|
||||
|
||||
# after the first read, always read the maximum size
|
||||
|
||||
$self->{'read_size'} = $max_read_size ;
|
||||
|
||||
# seek to the beginning of this block and save the new seek position
|
||||
|
||||
$seek_pos -= $read_size ;
|
||||
$self->{'seek_pos'} = $seek_pos ;
|
||||
seek( $handle, $seek_pos, 0 ) ;
|
||||
|
||||
#print "seek $seek_pos\n" ;
|
||||
|
||||
# read in the next (previous) block of text
|
||||
|
||||
$read_cnt = sysread( $handle, $read_buf, $read_size ) ;
|
||||
|
||||
#print "Read <$read_buf>\n" ;
|
||||
|
||||
# if ( $read_cnt != $read_size ) {
|
||||
# print "bad read cnt $read_cnt != size $read_size\n" ;
|
||||
# return( undef ) ;
|
||||
# }
|
||||
|
||||
# prepend the read buffer to the leftover (possibly partial) line
|
||||
|
||||
$text = $read_buf . ( pop @{$lines_ref} || '' ) ;
|
||||
|
||||
# split the buffer into a list of lines
|
||||
# this may want to be $/ but reading files backwards assumes plain text and
|
||||
# newline separators
|
||||
|
||||
@{$lines_ref} = $text =~ m[(^.*\n|^.+)]mg ;
|
||||
|
||||
#print "Lines \n=>", join( "<=\n=>", @{$lines_ref} ), "<=\n" ;
|
||||
}
|
||||
}
|
||||
|
||||
__END__
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Backwards.pm -- Read a file backwards by lines.
|
||||
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Backwards ;
|
||||
|
||||
# Object interface
|
||||
|
||||
$bw = Backwards->new( 'log_file' ) ;
|
||||
|
||||
while( $log_line = $bw->readline ) {
|
||||
print $log_line ;
|
||||
}
|
||||
|
||||
# Tied Handle Interface
|
||||
|
||||
tie *BW, 'log_file' ;
|
||||
|
||||
while( <BW> ) {
|
||||
print ;
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
||||
This module reads a file backwards line by line. It is simple to use,
|
||||
memory efficient and fast. It supports both an object and a tied handle
|
||||
interface.
|
||||
|
||||
It is intended for processing log and other similar text files which
|
||||
typically have new entries appended. It uses newline as the separator
|
||||
and not $/ since it is only meant to be used for text.
|
||||
|
||||
It works by reading large (8kb) blocks of text from the end of the file,
|
||||
splits them on newlines and stores the other lines until the buffer runs
|
||||
out. Then it seeks to the previous block and splits it. When it reaches
|
||||
the beginning of the file, it stops reading more blocks. All boundary
|
||||
conditions are handled correctly. If there is a trailing partial line
|
||||
(no newline) it will be the first line returned. Lines larger than the
|
||||
read buffer size are ok.
|
||||
|
||||
=head2 Object Interface
|
||||
|
||||
|
||||
There are only 2 methods in Backwards' object interface, new and
|
||||
readline.
|
||||
|
||||
=head2 new
|
||||
|
||||
New takes just a filename for an argument and it either returns the
|
||||
object on a successful open on that file or undef.
|
||||
|
||||
=head2 readline
|
||||
|
||||
Readline takes no arguments and it returns the previous line in the file
|
||||
or undef when there are no more lines in the file.
|
||||
|
||||
|
||||
=head2 Tied Handle Interface
|
||||
|
||||
The only tied handle calls supported are TIEHANDLE and READLINE and they
|
||||
are typeglobbed to new and readline respectively. All other tied handle
|
||||
operations will generate an unknown method error. Do not seek, write or
|
||||
do any other operation other than <> on the handle.
|
||||
1
mozilla/webtools/tinderbox/Empty.html
Normal file
1
mozilla/webtools/tinderbox/Empty.html
Normal file
@@ -0,0 +1 @@
|
||||
<font size=+2>Click on the <b>filename and line number</b> in the log and the source will appear in this window.</font>
|
||||
77
mozilla/webtools/tinderbox/Makefile
Executable file
77
mozilla/webtools/tinderbox/Makefile
Executable file
@@ -0,0 +1,77 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
# This Makefile helps you install Tinderbox. Define PERL and MYSQLTCL to
|
||||
# the full pathnames of where you have these utilities. Define PREFIX
|
||||
# to where you will install the running Tinderbox. Then "make install" should
|
||||
# copy things for you.
|
||||
|
||||
#BONSAI = /home/httpd/html/bonsai
|
||||
#CVSROOT = /cvsroot
|
||||
#GZIP = /usr/bin/gzip
|
||||
#PERL = /usr/bin/perl
|
||||
#PREFIX = /home/httpd/html/tinderbox
|
||||
#UUDECODE = /usr/bin/uudecode
|
||||
|
||||
FILES = addimage.cgi \
|
||||
addnote.cgi \
|
||||
admintree.cgi \
|
||||
buildwho.pl \
|
||||
clean.pl \
|
||||
copydata.pl \
|
||||
doadmin.cgi \
|
||||
ep_mac.pl \
|
||||
ep_unix.pl \
|
||||
ep_windows.pl \
|
||||
fixupimages.pl \
|
||||
globals.pl \
|
||||
handlemail.pl \
|
||||
imagelog.pl \
|
||||
processbuild.pl \
|
||||
showbuilds.cgi \
|
||||
showimages.cgi \
|
||||
showlog.cgi \
|
||||
Empty.html \
|
||||
faq.html \
|
||||
index.html \
|
||||
examples/mozilla-unix.pl \
|
||||
examples/mozilla-windows.pl
|
||||
|
||||
PICS = \
|
||||
1afi003r.gif \
|
||||
reledanim.gif \
|
||||
star.gif
|
||||
|
||||
install:
|
||||
mkdir -p $(PREFIX) && \
|
||||
for I in $(FILES); do \
|
||||
echo Installing $$I && \
|
||||
sed -e s#/usr/bonsaitools/bin/perl#$(PERL)#g \
|
||||
-e s#/tools/ns/bin/perl5#$(PERL)#g \
|
||||
-e s#/m/src#$(CVSROOT)#g \
|
||||
-e s#/usr/local/bin/gzip#$(GZIP)#g \
|
||||
-e s#/tools/ns/bin/uudecode#$(UUDECODE)#g \
|
||||
-e s#/d/webdocs/projects/bonsai#$(BONSAI)#g \
|
||||
$$I > $(PREFIX)/$$I && \
|
||||
chmod 755 $(PREFIX)/$$I; done && \
|
||||
for I in $(PICS); do \
|
||||
echo Installing $$I && \
|
||||
cp -f $$I $(PREFIX) && \
|
||||
chmod 755 $(PREFIX)/$$I; done
|
||||
|
||||
287
mozilla/webtools/tinderbox/README
Normal file
287
mozilla/webtools/tinderbox/README
Normal file
@@ -0,0 +1,287 @@
|
||||
This is Tinderbox. See <http://www.mozilla.org/tinderbox.html>.
|
||||
|
||||
|
||||
==========
|
||||
DISCLAIMER
|
||||
==========
|
||||
|
||||
This is not very well packaged code. It's not packaged at all. Don't
|
||||
come here expecting something you plop in a directory, twiddle a few
|
||||
things, and you're off and using it. Much work has to be done to get
|
||||
there. We'd like to get there, but it wasn't clear when that would be,
|
||||
and so we decided to let people see it first.
|
||||
|
||||
Don't believe for a minute that you can use this stuff without first
|
||||
understanding most of the code.
|
||||
|
||||
|
||||
============
|
||||
DEPENDENCIES
|
||||
============
|
||||
|
||||
To use tinderbox, you must first have bonsai up and running.
|
||||
See <http://www.mozilla.org/bonsai.html>.
|
||||
|
||||
Be warned now that bonsai is not easily installed.
|
||||
|
||||
|
||||
====================================
|
||||
What's What in the Tinderbox sources:
|
||||
====================================
|
||||
|
||||
This is a rough first pass at cataloging and documenting the Tinderbox
|
||||
sources. Many hands have been in this code over the years, and it has
|
||||
accreted wildly. There is probably quite a lot of dead code in here.
|
||||
|
||||
|
||||
PROGRAMS
|
||||
========
|
||||
|
||||
handlemail.pl This is the mail deliverty agent (MDA) for tinderbox,
|
||||
the local message transfer agent (MTA) calls this
|
||||
program to deliver the tinderbox mail into the system.
|
||||
It is a wrapper for processbuild.pl.
|
||||
|
||||
processbuild.pl Update the "$tbx{tree}/build.dat" database as new
|
||||
mail comes in then run "./buildwho.pl $tree" and
|
||||
"./showbuilds.cgi" (to build static versions of
|
||||
tinderbox data.
|
||||
|
||||
buildwho.pl Update the who.dat file with the list of authors who
|
||||
checked in in the last two days. This is run from
|
||||
processbuild.pl, always, and from showbuild.cgi when
|
||||
'rebuildguilty' is clicked
|
||||
|
||||
|
||||
Conceptually, the three programs, handlemail.pl, processbuild.pl, and
|
||||
buildwho.pl, make up the MDA for tinderbox.
|
||||
|
||||
|
||||
showbuilds.cgi Create the Tinderbox web page.
|
||||
|
||||
showlog.cgi Show a build log (brief and full) update the brief_log if
|
||||
necessary. Requires the ep_$form{errorparser}.pl error
|
||||
parser.
|
||||
|
||||
ep_unix.pl Knows how to parse Unix build error logs. Used by
|
||||
processbuild.pl There needs to be one ep_* file for
|
||||
each distinct parsing algorithm used, typically this
|
||||
is per platform. This file defines the regular
|
||||
expressions which locate error lines: has_error()
|
||||
has_warning() and the function has_errorline() which
|
||||
parses the line into the global variables:
|
||||
$error_file, $error_file_ref, $error_line, $error_guess,
|
||||
|
||||
admintree.cgi Displays the admin cgi which depends on:
|
||||
$message_of_day, $ignore_builds
|
||||
|
||||
doadmin.cgi Actually do the work to admin a tinderbox tree
|
||||
(change message of the day, turn off displays for a
|
||||
channel)
|
||||
|
||||
clean.pl Run `find . -name \"*.gz\" -mtime +7 -print ` and
|
||||
unlink those files. Does not appear to be run from
|
||||
other tools. It is a good candidate for a cron job.
|
||||
|
||||
|
||||
|
||||
OPTIONS to showbuilds.cgi
|
||||
=========================
|
||||
|
||||
Options to showbuilds are specified in the URL and are undocumented
|
||||
elsewhere.
|
||||
|
||||
If called with no 'tree' option display the possible build trees to
|
||||
pick from. The 'tree' picks the build to display. An additional tree
|
||||
can be specified with 'tree2'.
|
||||
|
||||
Interesting visual params are:
|
||||
|
||||
current state monitoring mode:
|
||||
express=1
|
||||
or
|
||||
panel=1
|
||||
text mode state monitoring:
|
||||
quickparse=1
|
||||
|
||||
These modes do not show on my browser:
|
||||
flash=1
|
||||
rdf=1
|
||||
static=1
|
||||
|
||||
These are self explanatory:
|
||||
nocrap=1;
|
||||
hours=n;
|
||||
|
||||
|
||||
EMAIL FORMAT
|
||||
============
|
||||
|
||||
Each tinderbox client mails status updates to the tinderbox server.
|
||||
These mails contain special tinderbox data lines describing the
|
||||
progress of the build it may also contain the log of the build process
|
||||
and could contain a uuencoded binary.
|
||||
|
||||
|
||||
The email to the tinderbox server looks like:
|
||||
|
||||
tinderbox: tree: Mozilla
|
||||
tinderbox: builddate: 900002087
|
||||
tinderbox: status: building
|
||||
tinderbox: build: IRIX 6.3 Depend
|
||||
tinderbox: errorparser: unix
|
||||
|
||||
If binaryname is set then the mail message is run through uudecode to
|
||||
create a file called "$binaryname" on the tinderbox server.
|
||||
|
||||
# NOT USED tinderbox: buildfamily: unix
|
||||
|
||||
|
||||
DATA STRUCTURES IN showbuilds.cgi
|
||||
=================================
|
||||
|
||||
load_buildlog() creates build_list a list of hash refernces of this
|
||||
type
|
||||
$buildrec = {
|
||||
mailtime => $mailtime,
|
||||
buildtime => $buildtime,
|
||||
buildname => ($tree2 ne '' ? $t->{name} . ' ' : '' ) . $buildname,
|
||||
errorparser => $errorparser,
|
||||
buildstatus => $buildstatus,
|
||||
logfile => $logfile,
|
||||
binaryname => $binaryname,
|
||||
td => $t
|
||||
};
|
||||
|
||||
the $buildrec->{rowspan} variable holds the number of rows that the build
|
||||
should occupy on the table and is not stored in the build.dat file.
|
||||
|
||||
These are other add ons to the data structure
|
||||
$buildrec->{hasnote}=1;
|
||||
$buildrec->{noteid} = (0+@note_array);
|
||||
|
||||
commonly buildrec's are accessed through:
|
||||
$build_table->[$build_time][$build_name] = $buildrec;
|
||||
|
||||
The list of users who updated this build is stored as:
|
||||
$who_list->[$checkin_time]->{$author} = 1;
|
||||
|
||||
There are numerous duplicate data structures which hold partial
|
||||
information:
|
||||
|
||||
hashes which hold all indices:
|
||||
$build_name_index->{$br->{buildname}} = 1;
|
||||
$build_time_index->{$br->{buildtime}} = 1;
|
||||
other access into $build_table:
|
||||
$build_name_names->[$i] = $n;
|
||||
$build_time_times->[$i] = $n;
|
||||
|
||||
|
||||
loadquickparseinfo creates these references
|
||||
$build->{$buildname} = $buildstatus;
|
||||
$times->{$buildname} = $buildtime;
|
||||
|
||||
|
||||
|
||||
DATA FILES
|
||||
==========
|
||||
|
||||
These files are used to store data structures. They are a persistent
|
||||
store of data between executions of the same program and they pass the
|
||||
data between cooperating program. This data is often databases with
|
||||
rows separated by "\n" and columns by '|'.
|
||||
|
||||
|
||||
$tree/${logfile}
|
||||
$tree/${logfile}.brief.html
|
||||
$tree/ignorebuilds.pl
|
||||
$tree/mod.pl
|
||||
$tree/notes.txt
|
||||
$tree/treedata.pl
|
||||
$tree/who.dat
|
||||
$treename/build.dat
|
||||
|
||||
The logfile that the tinderbox client sent stored in gziped format.
|
||||
The filename is ${tree}/$builddate.$$.gz so its quite random and does
|
||||
not depend on the clients$build string and multiple logs are kept for
|
||||
each build, one for each mail message sent.
|
||||
|
||||
The brief.html file is a cache of the error log summary for this log
|
||||
file and is recreated when the logfile gets updated.
|
||||
|
||||
ignorebuilds.pl is a file which specifies builds that should not be
|
||||
performed. It is valid perl code which sets the hash reference
|
||||
$ignore_builds, each key is a tree name.
|
||||
|
||||
mod.pl stores the tree specific message of the day. This is not to be
|
||||
confused with mod perl the CGI library. Its contents looks like:
|
||||
$message_of_day = 'message';
|
||||
|
||||
notes.txt store the database of notes:
|
||||
$buildtime|$buildname||$author|$time_now|$note
|
||||
|
||||
|
||||
treedata.pl stores the cvs information pertaining to this tree and
|
||||
looks like this:
|
||||
$cvs_module='$modulename';
|
||||
$cvs_branch='$branchname';
|
||||
$cvs_root='$repository';
|
||||
|
||||
who.dat file has lines like:
|
||||
$checkin_time|$author
|
||||
This gets stored in the data structure, where checkin_time
|
||||
gets fudged up so that is is a time already in the
|
||||
build_table:
|
||||
$who_list->[$checkin_time]->{$author} = 1;
|
||||
|
||||
build.dat stores the build results table. It is a flat file
|
||||
representation of $build_table
|
||||
|
||||
build.dat is a database file each row is a build and has pipe
|
||||
separated columns:
|
||||
|
||||
1) the time stamp of the tinderbox server
|
||||
2) time stamp of the build machine
|
||||
3) the official build name (should include build machine name)
|
||||
( note: that 2 & 3 together uniquely identify the build
|
||||
and all relevant build data)
|
||||
4) the architecture dependent error parser to use on the log files
|
||||
5) status of the build (success|busted|building|testfailed)
|
||||
6) The log file for this build (if completed)
|
||||
7) the name of the binary (if any) that came from the build
|
||||
|
||||
|
||||
Other Files
|
||||
====================
|
||||
1afi003r.gif The "flames" animation used by showbuilds.cgi
|
||||
|
||||
Empty.html Document used for an empty frame by ???
|
||||
|
||||
addimage.cgi The form that lets you add a new image to the list of
|
||||
images that Tinderbox picks from randomly.
|
||||
|
||||
addnote.cgi Add a note to a build log.
|
||||
|
||||
admintree.cgi Lets you perform various admin tasks on a Tinderbox tree.
|
||||
This just prompts for a password and posts to doadmin.cgi.
|
||||
|
||||
clean.pl ???
|
||||
copydata.pl ???
|
||||
|
||||
doadmin.cgi Actually do the work to admin a tinderbox tree
|
||||
|
||||
ep_mac.pl Knows how to parse Mac build error logs. Used by ???
|
||||
ep_unix.pl Knows how to parse Unix build error logs. Used by ???
|
||||
ep_windows.pl Knows how to parse Windows build error logs. Used by ???
|
||||
|
||||
faq.html Wildly out of date.
|
||||
|
||||
fixupimages.pl ???
|
||||
globals.pl ???
|
||||
imagelog.pl ???
|
||||
index.html ???
|
||||
reledanim.gif ???
|
||||
|
||||
showimages.cgi Show all the images in the Tinderbox list. Password-protected.
|
||||
|
||||
star.gif The "star" image used to annotate builds by ???
|
||||
404
mozilla/webtools/tinderbox/addimage.cgi
Executable file
404
mozilla/webtools/tinderbox/addimage.cgi
Executable file
@@ -0,0 +1,404 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use Socket;
|
||||
|
||||
use lib "../bonsai";
|
||||
require 'header.pl';
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
EmitHtmlTitleAndHeader("tinderbox: add images", "add images");
|
||||
|
||||
$| = 1;
|
||||
|
||||
require "globals.pl";
|
||||
require "imagelog.pl";
|
||||
|
||||
&split_cgi_args;
|
||||
|
||||
|
||||
sub Error {
|
||||
my ($msg) = @_;
|
||||
print "<BR><BR><BR>";
|
||||
print "<UL><FONT SIZE='+1'><B>Something went wrong:</B><P>";
|
||||
print "<UL>";
|
||||
print $msg;
|
||||
print "</UL>";
|
||||
print "<P>";
|
||||
print "Hit <B>\`Back'</B> and try again.";
|
||||
print "</UL>";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
if( $url = $form{"url"} ){
|
||||
$quote = $form{"quote"};
|
||||
|
||||
$quote =~ s/[\r\n]/ /g;
|
||||
$url =~ s/[\r\n]/ /g;
|
||||
|
||||
$width = "";
|
||||
$height = "";
|
||||
# I think we don't want to allow this --jwz
|
||||
# $width = $form{"width"};
|
||||
# $height = $form{"height"};
|
||||
|
||||
if ($width eq "" || $height eq "") {
|
||||
$size = &URLsize($url);
|
||||
if ($size =~ /WIDTH=([0-9]*)/) {
|
||||
$width = $1;
|
||||
}
|
||||
if ($size =~ /HEIGHT=([0-9]*)/) {
|
||||
$height = $1;
|
||||
}
|
||||
if ($width eq "" || $height eq "") {
|
||||
Error "Couldn't get image size for \"$url\".\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "
|
||||
|
||||
<P><center><img border=2 src='$url' width=$width height=$height><br>
|
||||
<i>$quote</i><br><br>
|
||||
";
|
||||
|
||||
if( $form{"submit"} ne "Yes" ){
|
||||
my $u2 = $url;
|
||||
my $q2 = $quote;
|
||||
$u2 =~ s@&@&@g; $u2 =~ s@<@<@g; $u2 =~ s@\"@"@g;
|
||||
$q2 =~ s@&@&@g; $q2 =~ s@<@<@g; $q2 =~ s@\"@"@g;
|
||||
|
||||
print "
|
||||
<form action='addimage.cgi' METHOD='get'>
|
||||
<input type=hidden name=url value=\"$u2\">
|
||||
<input type=hidden name=quote value=\"$q2\">
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TH ALIGN=RIGHT NOWRAP>Image URL:</TH>
|
||||
<TD><TT><B>$u2</B></TT></TD>
|
||||
</TR><TR>
|
||||
<TH ALIGN=RIGHT>Caption:</TH>
|
||||
<TD><TT><B>$q2</B></TT></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD></TD>
|
||||
<TD>
|
||||
<FONT SIZE=+2><B>
|
||||
Does that look right?
|
||||
<SPACER SIZE=10>
|
||||
<INPUT Type='submit' name='submit' value='Yes'>
|
||||
</B><BR>(If not, hit \`Back' and fix it.)
|
||||
</FONT>
|
||||
</TD>
|
||||
</TABLE>
|
||||
</form>
|
||||
";
|
||||
}
|
||||
else {
|
||||
&add_imagelog( $url, $quote, $width, $height );
|
||||
print "<br><br>
|
||||
<font size=+2>Has been added</font><br><br>
|
||||
<a href=showbuilds.cgi>Return to Log</a>";
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
print "
|
||||
<h2>Add an image and a funny caption.</h2>
|
||||
|
||||
<ul>
|
||||
<p>This is about fun, and making your daily excursion to
|
||||
<A HREF=http://www.mozilla.org/tinderbox.html>Tinderbox</A> a
|
||||
novel experience. Engineers spend a lot of time here; it might as well
|
||||
have some entertainment value.
|
||||
|
||||
<p>Please play nice. We don't have the time or inclination to look at
|
||||
everything you people submit, but if we get nastygrams or legalgrams
|
||||
and have to take something down, we will curse your IP address, and you
|
||||
might even make it so the whole thing goes away forever. Please don't
|
||||
make us go there. You might also avoid links to big images or slow
|
||||
servers.
|
||||
|
||||
<p><ul><B>Thank you for playing nice.</B></UL>
|
||||
|
||||
<p>If you really find an image offensive, please
|
||||
<A HREF=mailto:terry\@netscape.com?Subject=offensive%20tinderbox%20image>tell us</A>
|
||||
nicely before someone causes a stink. Be sure to include the URL of
|
||||
the image. Remember, we don't screen these submissions and may not
|
||||
have even seen it.
|
||||
|
||||
<p><ul><B>P.S. Please, no more pictures of Bill Gates.</B></UL>
|
||||
</ul>
|
||||
|
||||
<p><form action='addimage.cgi' METHOD='get'>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TH ALIGN=RIGHT NOWRAP>Image URL:</TH>
|
||||
<TD><INPUT NAME='url' SIZE=60></TD>
|
||||
</TR><TR>
|
||||
<TH ALIGN=RIGHT>Caption:</TH>
|
||||
<TD><INPUT NAME='quote' SIZE=60></TD>
|
||||
</TR><TR>
|
||||
<TD></TD>
|
||||
<TD><B>
|
||||
<INPUT Type='submit' name='submit' value='Test'>
|
||||
<SPACER SIZE=25>
|
||||
<INPUT Type='reset' name='reset' value='Reset'>
|
||||
</B></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
</form>
|
||||
<br><br>
|
||||
";
|
||||
}
|
||||
|
||||
sub split_cgi_args {
|
||||
local($i,$var,$value, $s);
|
||||
|
||||
$s = $ENV{"QUERY_STRING"};
|
||||
|
||||
@args= split(/\&/, $s );
|
||||
|
||||
for $i (@args) {
|
||||
($var, $value) = split(/=/, $i);
|
||||
$value =~ tr/+/ /;
|
||||
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
$form{$var} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#sub imgsize {
|
||||
# local($file)= @_;
|
||||
#
|
||||
# #first try to open the file
|
||||
# if( !open(STREAM, "<$file") ){
|
||||
# Error "Can't open IMG $file";
|
||||
## $size="";
|
||||
# } else {
|
||||
# if ($file =~ /.jpg/i || $file =~ /.jpeg/i) {
|
||||
# $size = &jpegsize(STREAM);
|
||||
# } elsif($file =~ /.gif/i) {
|
||||
# $size = &gifsize(STREAM);
|
||||
# } elsif($file =~ /.xbm/i) {
|
||||
# $size = &xbmsize(STREAM);
|
||||
# } else {
|
||||
# return "";
|
||||
# }
|
||||
# $_ = $size;
|
||||
# if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
# ($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
# }
|
||||
# if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
# ($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
# }
|
||||
# close(STREAM);
|
||||
# }
|
||||
# return $size;
|
||||
#}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine gets the size of the specified GIF
|
||||
###########################################################################
|
||||
|
||||
# bug: it thinks that
|
||||
# http://cvs1.mozilla.org/webtools/tinderbox/data/knotts.gif
|
||||
# is 640x400, but it's really 200x245.
|
||||
# giftrans says of that image:
|
||||
#
|
||||
# Header: "GIF87a"
|
||||
# Logical Screen Descriptor:
|
||||
# Logical Screen Width: 640 pixels
|
||||
# Logical Screen Height: 480 pixels
|
||||
# Image Descriptor:
|
||||
# Image Width: 200 pixels
|
||||
# Image Height: 245 pixels
|
||||
|
||||
|
||||
sub gifsize {
|
||||
local($GIF) = @_;
|
||||
read($GIF, $type, 6);
|
||||
if(!($type =~ /GIF8[7,9]a/) ||
|
||||
!(read($GIF, $s, 4) == 4) ){
|
||||
Error "Invalid or Corrupted GIF";
|
||||
$size="";
|
||||
} else {
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join ("", 'WIDTH=', $b<<8|$a, ' HEIGHT=', $d<<8|$c);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
sub xbmsize {
|
||||
local($XBM) = @_;
|
||||
local($input)="";
|
||||
|
||||
$input .= <$XBM>;
|
||||
$input .= <$XBM>;
|
||||
$_ = $input;
|
||||
if( /#define\s*\S*\s*\d*\s*\n#define\s*\S*\s*\d*\s*\n/i ){
|
||||
($a,$b)=/#define\s*\S*\s*(\d*)\s*\n#define\s*\S*\s*(\d*)\s*\n/i;
|
||||
$size=join ("", 'WIDTH=', $a, ' HEIGHT=', $b );
|
||||
} else {
|
||||
Error "Doesn't look like an XBM file";
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
# jpegsize : gets the width and height (in pixels) of a jpeg file
|
||||
# Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995
|
||||
# modified slightly by alex@ed.ac.uk
|
||||
sub jpegsize {
|
||||
local($JPEG) = @_;
|
||||
local($done)=0;
|
||||
$size="";
|
||||
|
||||
read($JPEG, $c1, 1); read($JPEG, $c2, 1);
|
||||
if( !((ord($c1) == 0xFF) && (ord($c2) == 0xD8))){
|
||||
my $s = sprintf "This is not a JPEG! (Codes %02X %02X)\n", ord($c1), ord($c2);
|
||||
Error $s;
|
||||
$done=1;
|
||||
}
|
||||
while (ord($ch) != 0xDA && !$done) {
|
||||
# Find next marker (JPEG markers begin with 0xFF)
|
||||
# This can hang the program!!
|
||||
while (ord($ch) != 0xFF) { read($JPEG, $ch, 1); }
|
||||
# JPEG markers can be padded with unlimited 0xFF's
|
||||
while (ord($ch) == 0xFF) { read($JPEG, $ch, 1); }
|
||||
# Now, $ch contains the value of the marker.
|
||||
$marker=ord($ch);
|
||||
|
||||
if (($marker >= 0xC0) && ($marker <= 0xCF) &&
|
||||
($marker != 0xC4) && ($marker != 0xCC)) { # it's a SOFn marker
|
||||
read ($JPEG, $junk, 3); read($JPEG, $s, 4);
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join("", 'HEIGHT=',$a<<8|$b,' WIDTH=',$c<<8|$d );
|
||||
$done=1;
|
||||
} else {
|
||||
# We **MUST** skip variables, since FF's within variable
|
||||
# names are NOT valid JPEG markers
|
||||
read ($JPEG, $s, 2);
|
||||
($c1, $c2) = unpack("C"x2,$s);
|
||||
$length = $c1<<8|$c2;
|
||||
if( ($length < 2) ){
|
||||
Error "Bad JPEG file: erroneous marker length";
|
||||
$done=1;
|
||||
} else {
|
||||
read($JPEG, $junk, $length-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine grabs a gif from another server and gets its size
|
||||
###########################################################################
|
||||
|
||||
|
||||
sub URLsize {
|
||||
my ($fullurl) = @_;
|
||||
|
||||
$_ = $fullurl;
|
||||
if ( ! m@^http://@ ) {
|
||||
Error "HTTP URLs only, please: \"$_\" is no good.";
|
||||
}
|
||||
|
||||
my($dummy, $dummy, $serverstring, $url) = split(/\//, $fullurl, 4);
|
||||
my($them,$port) = split(/:/, $serverstring);
|
||||
my $port = 80 unless $port;
|
||||
my $size="";
|
||||
|
||||
$_ = $them;
|
||||
if ( m@^[^.]*$@ ) {
|
||||
Error "Fully-qualified host names only, please: \"$_\" is no good.";
|
||||
}
|
||||
|
||||
$_=$url;
|
||||
my ($remote, $iaddr, $paddr, $proto, $line);
|
||||
$remote = $them;
|
||||
if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
|
||||
die "No port" unless $port;
|
||||
$iaddr = inet_aton($remote) || die "no host: $remote";
|
||||
$paddr = sockaddr_in($port, $iaddr);
|
||||
|
||||
$proto = getprotobyname('tcp');
|
||||
socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
|
||||
connect(S, $paddr) || die "connect: $!";
|
||||
select(S); $| = 1; select(STDOUT);
|
||||
|
||||
print S "GET /$url HTTP/1.0\r\n";
|
||||
print S "Host: $them\r\n";
|
||||
print S "User-Agent: Tinderbox/0.0\r\n";
|
||||
print S "\r\n";
|
||||
|
||||
$_ = <S>;
|
||||
if (! m@^HTTP/[0-9.]+ 200@ ) {
|
||||
Error "$them responded:<BR> $_";
|
||||
}
|
||||
|
||||
my $ctype = "";
|
||||
while (<S>) {
|
||||
# print "read: $_<br>\n";
|
||||
if ( m@^Content-Type:[ \t]*([^ \t\r\n]+)@io ) {
|
||||
$ctype = $1;
|
||||
}
|
||||
last if (/^[\r\n]/);
|
||||
}
|
||||
|
||||
$_ = $ctype;
|
||||
if ( $_ eq "" ) {
|
||||
Error "Server returned no content-type for \"$fullurl\"?";
|
||||
} elsif ( m@image/jpeg@i || m@image/pjpeg@i ) {
|
||||
$size = &jpegsize(S);
|
||||
} elsif ( m@image/gif@i ) {
|
||||
$size = &gifsize(S);
|
||||
} elsif ( m@image/xbm@i || m@image/x-xbm@i || m@image/x-xbitmap@i ) {
|
||||
$size = &xbmsize(S);
|
||||
} else {
|
||||
Error "Not a GIF, JPEG, or XBM: that was of type \"$ctype\".";
|
||||
}
|
||||
|
||||
$_ = $size;
|
||||
if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
|
||||
if ( $newwidth eq "" || $newheight eq "" ) {
|
||||
return "";
|
||||
} else {
|
||||
if ( $newwidth <= 5 || $newheight <= 5 ) {
|
||||
Error "${newwidth}x${newheight} seems small, don't you think?";
|
||||
} elsif ( $newwidth >= 400 || $newheight >= 400 ) {
|
||||
Error "${newwidth}x${newheight} is too big; please" .
|
||||
" keep it under 400x400."
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
}
|
||||
|
||||
sub dokill {
|
||||
kill 9,$child if $child;
|
||||
}
|
||||
206
mozilla/webtools/tinderbox/addnote.cgi
Executable file
206
mozilla/webtools/tinderbox/addnote.cgi
Executable file
@@ -0,0 +1,206 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib "../bonsai";
|
||||
use Fcntl;
|
||||
|
||||
require "globals.pl";
|
||||
require 'lloydcgi.pl';
|
||||
|
||||
if (defined($args = $form{log})) {
|
||||
|
||||
($tree, $logfile) = split /\//, $args;
|
||||
|
||||
my $br = find_build_record($tree, $logfile);
|
||||
$errorparser = $br->{errorparser};
|
||||
$buildname = $br->{buildname};
|
||||
$buildtime = $br->{buildtime};
|
||||
} else {
|
||||
$tree = $form{'tree'};
|
||||
$logfile = $form{'logfile'};
|
||||
$errorparser = $form{'errorparser'};
|
||||
$buildname = $form{'buildname'};
|
||||
$buildtime = $form{'buildtime'};
|
||||
}
|
||||
|
||||
$enc_buildname = &url_encode($buildname);
|
||||
|
||||
$note = $form{'note'};
|
||||
$who = $form{'who'};
|
||||
|
||||
$now = time;
|
||||
$now_str = &print_time($now);
|
||||
|
||||
$|=1;
|
||||
|
||||
if( -r "$tree/ignorebuilds.pl" ){
|
||||
require "$tree/ignorebuilds.pl";
|
||||
}
|
||||
|
||||
print "Content-Type:text/html\n";
|
||||
if ($ENV{"REQUEST_METHOD"} eq 'POST' && defined($form{'note'})) {
|
||||
# Expire the cookie 5 months from now
|
||||
print "Set-Cookie: email=$form{who}; expires="
|
||||
. toGMTString(time + 86400 * 152) . "; path=/\n";
|
||||
}
|
||||
print "\n<HTML>\n";
|
||||
|
||||
if( $url = $form{"note"} ){
|
||||
|
||||
$note =~ s/\&/&/gi;
|
||||
$note =~ s/\</</gi;
|
||||
$note =~ s/\>/>/gi;
|
||||
$enc_note = url_encode( $note );
|
||||
|
||||
open( NOTES,">>$tree/notes.txt");
|
||||
flock(NOTES, LOCK_EX);
|
||||
print NOTES "$buildtime|$buildname|$who|$now|$enc_note\n";
|
||||
|
||||
&LoadBuildTable;
|
||||
|
||||
foreach $element (keys %form) {
|
||||
|
||||
if(exists ${$build_name_index}{$element}) {
|
||||
print NOTES "${$build_name_index}{$element}|$element|$who|$now|$enc_note\n";
|
||||
} #EndIf
|
||||
} #Endforeach
|
||||
close(NOTES);
|
||||
|
||||
print "<H1>The following comment has been added to the log</h1>\n";
|
||||
|
||||
#print "$buildname \n $buildtime \n $errorparser \n $logfile \n $tree \n $enc_buildname \n";
|
||||
print "<pre>\n[<b>$who - $now_str</b>]\n$note\n</pre>";
|
||||
|
||||
print"
|
||||
<p><a href=\"showlog.cgi?tree=$tree\&buildname=$enc_buildname\&buildtime=$buildtime\&logfile=$logfile\&errorparser=$errorparser\">
|
||||
Go back to the Error Log</a>
|
||||
<a href=\"showbuilds.cgi?tree=$tree\">
|
||||
<br>Go back to the build Page</a>";
|
||||
|
||||
# Build tinderbox static pages
|
||||
$ENV{QUERY_STRING}="tree=$tree&static=1";
|
||||
$ENV{REQUEST_METHOD}="GET";
|
||||
system './showbuilds.cgi >/dev/null';
|
||||
|
||||
} else {
|
||||
|
||||
&GetBuildNameIndex;
|
||||
|
||||
@names = sort (keys %$build_name_index);
|
||||
|
||||
if ($buildname eq '' || $buildtime == 0) {
|
||||
print "<h1>Invalid parameters</h1>\n";
|
||||
die "\n";
|
||||
}
|
||||
|
||||
#print "$buildname \n $buildtime \n $errorparser \n $logfile \n $tree \n $enc_buildname \n";
|
||||
|
||||
$emailvalue = '';
|
||||
$emailvalue = " value='$cookie_jar{email}'" if defined($cookie_jar{email});
|
||||
|
||||
print qq(
|
||||
<head><title>Add a Comment to $buildname log</title></head>
|
||||
<body BGCOLOR="#FFFFFF" TEXT="#000000"LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
|
||||
|
||||
<table><tr><td>
|
||||
<b><font size="+2">Add a Log Comment</font></b>
|
||||
</td></tr><tr><td>
|
||||
<b><code>$buildname</code></b>
|
||||
</td></tr></table>
|
||||
|
||||
<form action='addnote.cgi' METHOD='post'>
|
||||
|
||||
<INPUT Type='hidden' name='buildname' value='${buildname}'>
|
||||
<INPUT Type='hidden' name='buildtime' value='${buildtime}'>
|
||||
<INPUT Type='hidden' name='errorparser' value='$errorparser'>
|
||||
<INPUT Type='hidden' name='logfile' value='$logfile'>
|
||||
<INPUT Type='hidden' name='tree' value='$tree'>
|
||||
|
||||
<table border=0 cellpadding=4 cellspacing=1>
|
||||
<tr valign=top>
|
||||
<td align=right>
|
||||
<NOWRAP>Email address:</NOWRAP>
|
||||
</td><td>
|
||||
<INPUT Type='input' name='who' size=32$emailvalue><BR>
|
||||
</td>
|
||||
</tr><tr valign=top>
|
||||
<td align=right>
|
||||
Comment:
|
||||
</td><td>
|
||||
<TEXTAREA NAME=note ROWS=10 COLS=30 WRAP=HARD></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br><b><font size="+2">Addition Builds</font></b><br>
|
||||
(Comment will be added to the most recent cycle.)<br>
|
||||
);
|
||||
|
||||
for $other_build (@names){
|
||||
if( $other_build ne "" ){
|
||||
|
||||
if (not exists ${$ignore_builds}{$other_build}) {
|
||||
if( $other_build ne $buildname ){
|
||||
print "<INPUT TYPE=checkbox NAME=\"$other_build\">";
|
||||
print "$other_build<BR>\n";
|
||||
}
|
||||
} #EndIf
|
||||
}
|
||||
} #Endfor
|
||||
|
||||
print "<INPUT Type='submit' name='submit' value='Add Comment'><BR>
|
||||
</form>\n</body>\n</html>";
|
||||
}
|
||||
|
||||
sub GetBuildNameIndex {
|
||||
local($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile, $binaryname);
|
||||
|
||||
open(BUILDLOG, "$tree/build.dat") or die "Couldn't open build.dat: $!\n";
|
||||
|
||||
while(<BUILDLOG>) {
|
||||
chomp;
|
||||
($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile, $binaryname) =
|
||||
split( /\|/ );
|
||||
|
||||
$build_name_index->{$buildname} = 0;
|
||||
|
||||
} #EndWhile
|
||||
close(BUILDLOG);
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub LoadBuildTable {
|
||||
local($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile, $binaryname);
|
||||
|
||||
open(BUILDLOG, "$tree/build.dat") or die "Couldn't open build.dat: $!\n";
|
||||
|
||||
while(<BUILDLOG>) {
|
||||
chomp;
|
||||
($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile, $binaryname) =
|
||||
split( /\|/ );
|
||||
|
||||
if ($buildtime > $build_name_index->{$buildname} ) {
|
||||
$build_name_index->{$buildname} = $buildtime;
|
||||
}
|
||||
|
||||
} #EndWhile
|
||||
close(BUILDLOG);
|
||||
|
||||
}
|
||||
|
||||
131
mozilla/webtools/tinderbox/admintree.cgi
Executable file
131
mozilla/webtools/tinderbox/admintree.cgi
Executable file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'globals.pl';
|
||||
require 'header.pl';
|
||||
|
||||
$|=1;
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
EmitHtmlHeader("administer tinderbox", "tree: $tree");
|
||||
|
||||
$form{noignore} = 1; # Force us to load all build info, not
|
||||
# paying any attention to ignore_builds stuff.
|
||||
$maxdate = time();
|
||||
$mindate = $maxdate - 24*60*60;
|
||||
&load_data;
|
||||
|
||||
if (defined($tree)) {
|
||||
if( -r "$tree/mod.pl" ){
|
||||
require "$tree/mod.pl";
|
||||
}
|
||||
else {
|
||||
$message_of_day = "";
|
||||
}
|
||||
|
||||
print "
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=set_message>
|
||||
<br><b>Message of the Day
|
||||
<br><TEXTAREA NAME=message ROWS=10 COLS=70 WRAP=SOFT>$message_of_day
|
||||
</TEXTAREA>
|
||||
<br><INPUT TYPE=SUBMIT VALUE='Set Message of the Day'>
|
||||
</FORM>
|
||||
<hr>
|
||||
";
|
||||
|
||||
|
||||
print "
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=trim_logs>
|
||||
<br><b>Trim Logs to <INPUT NAME=days size=5 VALUE='7'> days.</b> (Tinderbox
|
||||
shows 2 days history by default. You can see more by clicking show all).
|
||||
<br><INPUT TYPE=SUBMIT VALUE='Trim Logs'>
|
||||
</FORM>
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<hr>
|
||||
" ;
|
||||
}
|
||||
|
||||
print "
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=create_tree>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD><B>tinderbox tree name:</B></TD>
|
||||
<TD><INPUT NAME=treename VALUE=''></TD>
|
||||
</TR><TR>
|
||||
<TD><B>cvs repository:</B></TD>
|
||||
<TD><INPUT NAME=repository VALUE=''></TD>
|
||||
</TR><TR>
|
||||
<TD><B>cvs module name:</B></TD>
|
||||
<TD><INPUT NAME=modulename VALUE=''></TD>
|
||||
</TR><TR>
|
||||
<TD><B>cvs branch:</B></TD>
|
||||
<TD><INPUT NAME=branchname VALUE='HEAD'></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<INPUT TYPE=SUBMIT VALUE='Create a new Tinderbox page'>
|
||||
</FORM>
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<hr>
|
||||
";
|
||||
|
||||
if (defined($tree)) {
|
||||
print "
|
||||
<B><font size=+1>If builds are behaving badly you can turn them off.</font></b><br> Uncheck
|
||||
the build that is misbehaving and click the button. You can still see all the
|
||||
builds even if some are disabled by adding the parameter <b><tt>&noignore=1</tt></b> to
|
||||
the tinderbox URL.<br>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=disable_builds>
|
||||
";
|
||||
|
||||
@names = sort (@$build_name_names) ;
|
||||
|
||||
for $i (@names){
|
||||
if( $i ne "" ){
|
||||
$checked = ($ignore_builds->{$i} != 0 ? "": "CHECKED" );
|
||||
print "<INPUT TYPE=checkbox NAME='build_$i' $checked >";
|
||||
print "$i<br>\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "
|
||||
<INPUT TYPE=SUBMIT VALUE='Show only checked builds'>
|
||||
</FORM>
|
||||
<hr>
|
||||
";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
97
mozilla/webtools/tinderbox/buildwho.pl
Executable file
97
mozilla/webtools/tinderbox/buildwho.pl
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'globals.pl';
|
||||
|
||||
$F_DEBUG=1;
|
||||
|
||||
|
||||
$days = 2;
|
||||
|
||||
if ($ARGV[0] eq "-days") {
|
||||
shift @ARGV;
|
||||
$days = shift @ARGV;
|
||||
}
|
||||
|
||||
$tree = $ARGV[0];
|
||||
|
||||
open(SEMFILE, ">>$tree/buildwho.sem") || die "Couldn't open semaphore file!";
|
||||
if (!flock(SEMFILE, 2 + 4)) { # 2 means "lock"; 4 means "fail immediately if
|
||||
# lock already taken".
|
||||
print "buildwho.pl: Another process is currently building the database.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
require "$tree/treedata.pl";
|
||||
|
||||
if( $cvs_root eq '' ){
|
||||
$CVS_ROOT = '/m/src';
|
||||
}
|
||||
else {
|
||||
$CVS_ROOT = $cvs_root;
|
||||
}
|
||||
|
||||
$CVS_REPOS_SUFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFIX =~ s/\//_/g;
|
||||
|
||||
$CHECKIN_DATA_FILE = "/d/webdocs/projects/bonsai/data/checkinlog${CVS_REPOS_SUFIX}";
|
||||
$CHECKIN_INDEX_FILE = "/d/webdocs/projects/bonsai/data/index${CVS_REPOS_SUFIX}";
|
||||
|
||||
require 'cvsquery.pl';
|
||||
|
||||
print "cvsroot='$CVS_ROOT'\n";
|
||||
|
||||
&build_who;
|
||||
|
||||
flock(SEMFILE, 8); # '8' is magic 'unlock' const.
|
||||
close SEMFILE;
|
||||
|
||||
|
||||
sub build_who {
|
||||
open(BUILDLOG, "<$tree/build.dat" );
|
||||
$line = <BUILDLOG>;
|
||||
close(BUILDLOG);
|
||||
|
||||
#($j,$query_date_min) = split(/\|/, $line);
|
||||
$query_date_min = time - (60 * 60 * 24 * $days);
|
||||
|
||||
if( $F_DEBUG ){
|
||||
print "Minimum date: $query_date_min\n";
|
||||
}
|
||||
|
||||
$query_module=$cvs_module;
|
||||
$query_branch=$cvs_branch;
|
||||
|
||||
$result = &query_checkins;
|
||||
|
||||
|
||||
$last_who='';
|
||||
$last_date=0;
|
||||
open(WHOLOG, ">$tree/who.dat" );
|
||||
for $ci (@$result) {
|
||||
if( $ci->[$CI_DATE] != $last_date || $ci->[$CI_WHO] != $last_who ){
|
||||
print WHOLOG "$ci->[$CI_DATE]|$ci->[$CI_WHO]\n";
|
||||
}
|
||||
$last_who=$ci->[$CI_WHO];
|
||||
$last_date=$ci->[$CI_DATE];
|
||||
}
|
||||
close( WHOLOG );
|
||||
}
|
||||
124
mozilla/webtools/tinderbox/bustagestats.cgi
Executable file
124
mozilla/webtools/tinderbox/bustagestats.cgi
Executable file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'globals.pl';
|
||||
require 'header.pl';
|
||||
|
||||
use Date::Parse;
|
||||
use Date::Format;
|
||||
|
||||
my $TIMEFORMAT = "%D %T";
|
||||
|
||||
$|=1;
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
# &load_data;
|
||||
|
||||
EmitHtmlHeader("Statistics");
|
||||
|
||||
my $tree = $form{'tree'};
|
||||
my $start = $form{'start'};
|
||||
my $end = $form{'end'};
|
||||
|
||||
sub str2timeAndCheck {
|
||||
my ($str) = (@_);
|
||||
my $result = str2time($str);
|
||||
if (defined $result && $result > 7000000) {
|
||||
return $result;
|
||||
}
|
||||
print "<p><font color=red>Can't parse as a date: $str</font><p>\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (defined $tree && defined $start && defined $end) {
|
||||
my $first = str2timeAndCheck($start);
|
||||
my $last = str2timeAndCheck($end);
|
||||
if ($first > 0 && $last > 0) {
|
||||
if (open(IN, "<$tree/build.dat")) {
|
||||
print "<hr><center><h1>Bustage stats for $tree</H1><H3>from " .
|
||||
time2str($TIMEFORMAT, $first) . " to " .
|
||||
time2str($TIMEFORMAT, $last) . "</H3></center>\n";
|
||||
my %stats;
|
||||
while (<IN>) {
|
||||
chomp;
|
||||
my ($mailtime, $buildtime, $buildname, $errorparser,
|
||||
$buildstatus, $logfile, $binaryname) =
|
||||
split( /\|/ );
|
||||
if ($buildtime >= $first && $buildtime <= $last) {
|
||||
if (!defined $stats{$buildname}) {
|
||||
$stats{$buildname} = 0;
|
||||
}
|
||||
if ($buildstatus eq "busted") {
|
||||
$stats{$buildname}++;
|
||||
}
|
||||
}
|
||||
}
|
||||
print "<table>\n";
|
||||
print "<tr><th>Build name</th><th>Number of bustages</th></tr>\n";
|
||||
foreach my $key (sort (keys %stats)) {
|
||||
print "<tr><td>$key</td><td>$stats{$key}</td></tr>\n";
|
||||
}
|
||||
print "</table>\n";
|
||||
} else {
|
||||
print "<p><font color=red>There does not appear to be a tree " .
|
||||
"named '$tree'.</font><p>";
|
||||
}
|
||||
|
||||
}
|
||||
print "<hr>\n";
|
||||
}
|
||||
|
||||
if (!defined $tree) {
|
||||
$tree = "";
|
||||
}
|
||||
|
||||
if (!defined $start) {
|
||||
$start = time2str($TIMEFORMAT, time() - 7*24*60*60); # One week ago.
|
||||
}
|
||||
|
||||
if (!defined $end) {
|
||||
$end = time2str($TIMEFORMAT, time()); # #now
|
||||
}
|
||||
|
||||
|
||||
print qq|
|
||||
<form>
|
||||
<table>
|
||||
<tr>
|
||||
<th align=right>Tree:</th>
|
||||
<td><input name=tree size=30 value="$tree"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align=right>Start time:</th>
|
||||
<td><input name=start size=30 value="$start"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align=right>End time:</th>
|
||||
<td><input name=end size=30 value="$end"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<INPUT TYPE=\"submit\" VALUE=\"Generate stats \">
|
||||
|
||||
</form>
|
||||
|;
|
||||
BIN
mozilla/webtools/tinderbox/channelflames.gif
Normal file
BIN
mozilla/webtools/tinderbox/channelflames.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
mozilla/webtools/tinderbox/channelok.gif
Normal file
BIN
mozilla/webtools/tinderbox/channelok.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 295 B |
42
mozilla/webtools/tinderbox/clean.pl
Executable file
42
mozilla/webtools/tinderbox/clean.pl
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# Figure out which directory tinderbox is in by looking at argv[0]
|
||||
|
||||
$tinderboxdir = $0;
|
||||
$tinderboxdir =~ s:/[^/]*$::; # Remove last word, and slash before it.
|
||||
if ($tinderboxdir eq "") {
|
||||
$tinderboxdir = ".";
|
||||
}
|
||||
|
||||
#print "tinderbox = $tinderboxdir\n";
|
||||
|
||||
chdir $tinderboxdir || die "Couldn't chdir to $tinderboxdir";
|
||||
|
||||
#print "cd ok\n";
|
||||
|
||||
open FL, "find . -name \"*.gz\" -mtime +7 -print |";
|
||||
|
||||
#print "find ok\n";
|
||||
|
||||
while( <FL> ){
|
||||
chop();
|
||||
#print "unlink $_\n";
|
||||
unlink $_;
|
||||
}
|
||||
BIN
mozilla/webtools/tinderbox/cont.gif
Normal file
BIN
mozilla/webtools/tinderbox/cont.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 B |
91
mozilla/webtools/tinderbox/copydata.pl
Executable file
91
mozilla/webtools/tinderbox/copydata.pl
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/tools/ns/bin/perl5
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
#
|
||||
# to run this script execute 'nohup copydata.pl &' from the tinderbox directory
|
||||
#
|
||||
|
||||
$start_dir = `pwd`;
|
||||
chop($start_dir);
|
||||
$scp_cmd = "scp -o 'User snapshot' -o'Port 22' -o 'UserKnownHostsFile /u/shaver/snapshot/known_hosts' -o 'IdentityFile /u/shaver/snapshot/identity'";
|
||||
|
||||
|
||||
$last_time = 0;
|
||||
|
||||
$min_cycle_time = 3 * 60; # 3 minutes
|
||||
|
||||
print "starting dir is :$start_dir\n";
|
||||
|
||||
while( 1 ){
|
||||
chdir("$start_dir");
|
||||
if( time - $last_time < $min_cycle_time ){
|
||||
$sleep_time = $min_cycle_time - (time - $last_time);
|
||||
print "\n\nSleeping $sleep_time seconds ...\n";
|
||||
sleep( $sleep_time );
|
||||
}
|
||||
|
||||
©_data("Mozilla");
|
||||
©_data("raptor");
|
||||
|
||||
chdir( "$start_dir");
|
||||
print "$scp_cmd * cvs1.mozilla.org:/e/webtools/tinderbox\n";
|
||||
system "$scp_cmd * cvs1.mozilla.org:/e/webtools/tinderbox";
|
||||
|
||||
chdir( "$start_dir/../bonsai");
|
||||
print "$scp_cmd * cvs1.mozilla.org:/e/webtools/bonsai\n";
|
||||
system "$scp_cmd * cvs1.mozilla.org:/e/webtools/bonsai";
|
||||
|
||||
|
||||
$last_time = time;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
sub copy_data {
|
||||
local($data_dir) = @_;
|
||||
local($zips,$qry);
|
||||
|
||||
chdir $data_dir || die "couldn't chdir to $data_dir";
|
||||
|
||||
system "echo hello >lastup.new";
|
||||
|
||||
if( -r 'lastup' ) {
|
||||
$qry = '-newer lastup.old';
|
||||
rename 'lastup', 'lastup.old'
|
||||
}
|
||||
rename 'lastup.new', 'lastup';
|
||||
|
||||
|
||||
open( FINDER, "find . $qry -name \"*.gz\" -print|" );
|
||||
while(<FINDER>){
|
||||
print;
|
||||
chop;
|
||||
$zips .= "$_ ";
|
||||
}
|
||||
close( FINDER );
|
||||
|
||||
unlink 'lastup.old';
|
||||
|
||||
print "$scp_cmd *.txt $zips *.dat cvs1.mozilla.org:/e/webtools/tinderbox/$data_dir\n";
|
||||
system "$scp_cmd *.txt $zips *.dat cvs1.mozilla.org:/e/webtools/tinderbox/$data_dir";
|
||||
|
||||
|
||||
chdir $start_dir || die "couldn't chdir to $start_dir";
|
||||
}
|
||||
217
mozilla/webtools/tinderbox/doadmin.cgi
Executable file
217
mozilla/webtools/tinderbox/doadmin.cgi
Executable file
@@ -0,0 +1,217 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
use lib "../bonsai";
|
||||
require 'lloydcgi.pl';
|
||||
require 'globals.pl';
|
||||
|
||||
umask O666;
|
||||
|
||||
|
||||
$|=1;
|
||||
|
||||
check_password();
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
$command = $form{'command'};
|
||||
$tree= $form{'tree'};
|
||||
|
||||
if( $command eq 'create_tree' ){
|
||||
&create_tree;
|
||||
}
|
||||
elsif( $command eq 'remove_build' ){
|
||||
&remove_build;
|
||||
}
|
||||
elsif( $command eq 'trim_logs' ){
|
||||
&trim_logs;
|
||||
}
|
||||
elsif( $command eq 'set_message' ){
|
||||
&set_message;
|
||||
}
|
||||
elsif( $command eq 'disable_builds' ){
|
||||
&disable_builds;
|
||||
} else {
|
||||
print "Unknown command: \"$command\".";
|
||||
}
|
||||
|
||||
sub trim_logs {
|
||||
$days = $form{'days'};
|
||||
$tree = $form{'tree'};
|
||||
|
||||
print "<h2>Trimming Log files for $tree...</h2>\n<p>";
|
||||
|
||||
$min_date = time - (60*60*24 * $days);
|
||||
|
||||
#
|
||||
# Nuke the old log files
|
||||
#
|
||||
$i = 0;
|
||||
opendir( D, 'DogbertTip' );
|
||||
while( $fn = readdir( D ) ){
|
||||
if( $fn =~ /\.gz$/ ){
|
||||
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,
|
||||
$ctime,$blksize,$blocks) = stat("$tree/$fn");
|
||||
if( $mtime && ($mtime < $min_date) ){
|
||||
print "$fn\n";
|
||||
$tblocks += $blocks;
|
||||
unlink( "$tree/$fn" );
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir( D );
|
||||
$k = $tblocks*512/1024;
|
||||
print "<br><b>$i Logfiles ( $k K bytes ) removed</b><br>\n";
|
||||
|
||||
#
|
||||
# Trim build.dat
|
||||
#
|
||||
$builds_removed = 0;
|
||||
open(BD, "<$tree/build.dat");
|
||||
open(NBD, ">$tree/build.dat.new");
|
||||
while( <BD> ){
|
||||
($mailtime,$buildtime,$buildname) = split( /\|/ );
|
||||
if( $buildtime >= $min_date ){
|
||||
print NBD $_;
|
||||
}
|
||||
else {
|
||||
$builds_removed++;
|
||||
}
|
||||
}
|
||||
close( BD );
|
||||
close( NBD );
|
||||
|
||||
rename( "$tree/build.dat", "$tree/build.dat.old" );
|
||||
rename( "$tree/build.dat.new", "$tree/build.dat" );
|
||||
|
||||
print "<h2>$builds_removed Builds removed from build.dat</h2>\n";
|
||||
}
|
||||
|
||||
sub create_tree {
|
||||
$treename = $form{'treename'};
|
||||
my $repository = $form{'repository'};
|
||||
$modulename = $form{'modulename'};
|
||||
$branchname = $form{'branchname'};
|
||||
|
||||
if( -r $treename ){
|
||||
chmod 0777, $treename;
|
||||
}
|
||||
else {
|
||||
mkdir( $treename, 0777 ) || die "<h1> Cannot mkdir $treename</h1>";
|
||||
}
|
||||
open( F, ">$treename/treedata.pl" );
|
||||
print F "\$cvs_module='$modulename';\n";
|
||||
print F "\$cvs_branch='$branchname';\n";
|
||||
if ($repository ne "") {
|
||||
print F "\$cvs_root='$repository';\n";
|
||||
}
|
||||
close( F );
|
||||
|
||||
open( F, ">$treename/build.dat" );
|
||||
close( F );
|
||||
|
||||
open( F, ">$treename/who.dat" );
|
||||
close( F );
|
||||
|
||||
open( F, ">$treename/notes.txt" );
|
||||
close( F );
|
||||
|
||||
chmod 0777, "$treename/build.dat", "$treename/who.dat", "$treename/notes.txt",
|
||||
"$treename/treedata.pl";
|
||||
|
||||
print "<h2><a href=showbuilds.cgi?tree=$treename>Tree created or modified</a></h2>\n";
|
||||
}
|
||||
|
||||
sub remove_build {
|
||||
$build_name = $form{'build'};
|
||||
|
||||
#
|
||||
# Trim build.dat
|
||||
#
|
||||
$builds_removed = 0;
|
||||
open(BD, "<$tree/build.dat");
|
||||
open(NBD, ">$tree/build.dat.new");
|
||||
while( <BD> ){
|
||||
($mailtime,$buildtime,$bname) = split( /\|/ );
|
||||
if( $bname ne $build_name ){
|
||||
print NBD $_;
|
||||
}
|
||||
else {
|
||||
$builds_removed++;
|
||||
}
|
||||
}
|
||||
close( BD );
|
||||
close( NBD );
|
||||
chmod( 0777, "$tree/build.dat.new");
|
||||
|
||||
rename( "$tree/build.dat", "$tree/build.dat.old" );
|
||||
rename( "$tree/build.dat.new", "$tree/build.dat" );
|
||||
|
||||
print "<h2><a href=showbuilds.cgi?tree=$tree>
|
||||
$builds_removed Builds removed from build.dat</a></h2>\n";
|
||||
}
|
||||
|
||||
sub disable_builds {
|
||||
my $i,%buildnames;
|
||||
$build_name = $form{'build'};
|
||||
|
||||
#
|
||||
# Trim build.dat
|
||||
#
|
||||
open(BD, "<$tree/build.dat");
|
||||
while( <BD> ){
|
||||
($mailtime,$buildtime,$bname) = split( /\|/ );
|
||||
$buildnames{$bname} = 0;
|
||||
}
|
||||
close( BD );
|
||||
|
||||
for $i (keys %form) {
|
||||
if ($i =~ /^build_/ ){
|
||||
$i =~ s/^build_//;
|
||||
$buildnames{$i} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
open(IGNORE, ">$tree/ignorebuilds.pl");
|
||||
print IGNORE '$ignore_builds = {' . "\n";
|
||||
for $i ( sort keys %buildnames ){
|
||||
if( $buildnames{$i} == 0 ){
|
||||
print IGNORE "\t\t'$i' => 1,\n";
|
||||
}
|
||||
}
|
||||
print IGNORE "\t};\n";
|
||||
|
||||
chmod( 0777, "$tree/ignorebuilds.pl");
|
||||
print "<h2><a href=showbuilds.cgi?tree=$treename>Build state Changed</a></h2>\n";
|
||||
}
|
||||
|
||||
|
||||
sub set_message {
|
||||
$m = $form{'message'};
|
||||
$m =~ s/\'/\\'/g;
|
||||
open(MOD, ">$tree/mod.pl");
|
||||
print MOD "\$message_of_day = \'$m\'\;\n1;";
|
||||
close(MOD);
|
||||
chmod( 0777, "$tree/mod.pl");
|
||||
print "<h2><a href=showbuilds.cgi?tree=$tree>
|
||||
Message Changed</a></h2>\n";
|
||||
}
|
||||
|
||||
45
mozilla/webtools/tinderbox/ep_mac.pl
Executable file
45
mozilla/webtools/tinderbox/ep_mac.pl
Executable file
@@ -0,0 +1,45 @@
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
1;
|
||||
#
|
||||
# Scan a line and see if it has an error
|
||||
#
|
||||
sub has_error {
|
||||
$line =~ /fatal error/ # link error
|
||||
|| $line =~ /Error / # C error
|
||||
|| $line =~ /\[checkout aborted\]/ #cvs error
|
||||
|| $line =~ /Couldn\'t find project file / # CW project error
|
||||
;
|
||||
}
|
||||
|
||||
sub has_warning {
|
||||
$line =~ /^[A-Za-z0-9_]+\.[A-Za-z0-9]+\ line [0-9]+/ ;
|
||||
}
|
||||
|
||||
sub has_errorline {
|
||||
local( $line ) = @_;
|
||||
if( $line =~ /^(([A-Za-z0-9_]+\.[A-Za-z0-9]+) line ([0-9]+))/ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = $2;
|
||||
$error_line = $3;
|
||||
$error_guess = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
59
mozilla/webtools/tinderbox/ep_unix.pl
Executable file
59
mozilla/webtools/tinderbox/ep_unix.pl
Executable file
@@ -0,0 +1,59 @@
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
1;
|
||||
#
|
||||
# Scan a line and see if it has an error
|
||||
#
|
||||
sub has_error {
|
||||
$line =~ /fatal error/ # link error
|
||||
|| $line =~ /^C / # cvs merge conflict
|
||||
|| $line =~ / Error: / # C error
|
||||
|| $line =~ / error\([0-9]*\)\:/ # C error
|
||||
|| ($line =~ /gmake/ && $line =~ / Error /)
|
||||
|| $line =~ /\[checkout aborted\]/ #cvs error
|
||||
|| $line =~ /\: cannot find module/ #cvs error
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
sub has_warning {
|
||||
$line =~ /^[A-Za-z0-9_]+\.[A-Za-z0-9]+\:[0-9]+\:/
|
||||
|| $line =~ /^\"[A-Za-z0-9_]+\.[A-Za-z0-9]+\"\, line [0-9]+\:/
|
||||
;
|
||||
}
|
||||
|
||||
sub has_errorline {
|
||||
local( $line ) = @_;
|
||||
if( $line =~ /^(([A-Za-z0-9_]+\.[A-Za-z0-9]+)\:([0-9]+)\:)/ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = $2;
|
||||
$error_line = $3;
|
||||
$error_guess = 1;
|
||||
return 1;
|
||||
}
|
||||
if ( $line =~ /^(\"([A-Za-z0-9_]+\.[A-Za-z0-9]+)\"\, line ([0-9]+)\:)/ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = $2;
|
||||
$error_line = $3;
|
||||
$error_guess = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
73
mozilla/webtools/tinderbox/ep_windows.pl
Executable file
73
mozilla/webtools/tinderbox/ep_windows.pl
Executable file
@@ -0,0 +1,73 @@
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
1;
|
||||
#
|
||||
# Scan a line and see if it has an error
|
||||
#
|
||||
sub has_error {
|
||||
$line =~ /fatal error/ # link error
|
||||
|| $line =~ / error / # C error
|
||||
|| $line =~ /^C / # cvs merge conflict
|
||||
|| $line =~ /error C/ # C error
|
||||
|| $line =~ /Creating new precompiled header/ # Wastes time.
|
||||
|| $line =~ /error:/ # java error
|
||||
|| $line =~ /jmake.MakerFailedException:/ # java error
|
||||
|| $line =~ /Unknown host / # cvs error
|
||||
|| $line =~ /: build failed\;/ # nmake error
|
||||
|| ($line =~ /gmake/ && $line =~ / Error /)
|
||||
|| $line =~ /\[checkout aborted\]/ #cvs error
|
||||
|| $line =~ /\: cannot find module/ #cvs error
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
sub has_warning {
|
||||
$line =~ /: warning/ # link error
|
||||
|| $line =~ / error / # C error
|
||||
;
|
||||
}
|
||||
|
||||
sub has_errorline {
|
||||
local( $line ) = @_;
|
||||
$error_file = ''; #'NS\CMD\WINFE\CXICON.cpp';
|
||||
$error_line = 0;
|
||||
|
||||
if( $line =~ m@(ns([\\/][a-z0-9\._]+)*)@i ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = lc $error_file;
|
||||
$error_file_ref =~ s@\\@/@g;
|
||||
|
||||
$line =~ m/\(([0-9]+)\)/;
|
||||
$error_line = $1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( $line =~ m@(^([A-Za-z0-9_]+\.[A-Za-z])+\(([0-9]+)\))@ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = lc $2;
|
||||
$error_line = $3;
|
||||
$error_guess=1;
|
||||
$error_file_ref =~ s@\\@/@g;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
44
mozilla/webtools/tinderbox/examples/README
Normal file
44
mozilla/webtools/tinderbox/examples/README
Normal file
@@ -0,0 +1,44 @@
|
||||
This directory contains example Tinderbox client scripts. These scripts are
|
||||
for illustration/documentation purposes only and are not maintained
|
||||
regularly. Current scripts to build mozilla will live in an another spot
|
||||
in the mozilla tree.
|
||||
|
||||
Three examples have been provided:
|
||||
|
||||
mozilla-windows.pl: perl script that drives mozilla tinderbox builds for Win32
|
||||
mozilla-unix.pl : perl script that drives mozilla tinderbox builds for UNIX
|
||||
build-moz-smoke.pl: perl script that drives mozilla tinderbox builds for UNIX,
|
||||
and subsequently runs the executable returning a green tree only if
|
||||
it does not crash.
|
||||
|
||||
These scripts show the basic elements of a Tinderbox client script. These
|
||||
elements are:
|
||||
|
||||
1) Sending a start e-mail to the Tinderbox server, in the form of a formatted
|
||||
mail message. Example:
|
||||
|
||||
tinderbox: tree: Mozilla
|
||||
tinderbox: builddate: 900002087
|
||||
tinderbox: status: building
|
||||
tinderbox: build: IRIX 6.3 Depend
|
||||
tinderbox: errorparser: unix
|
||||
tinderbox: buildfamily: unix
|
||||
|
||||
2) Obtain a source tree by performing a cvs checkout.
|
||||
|
||||
3) Perform the build, saving the output to a log file.
|
||||
|
||||
4) Determine if the build was successful or failed. This could be done either
|
||||
by checking for the presence of a binary, or being using error codes returned
|
||||
from the compile command.
|
||||
|
||||
5) Send a completion message to Tinderbox, identifying build success or
|
||||
failure. Example:
|
||||
|
||||
tinderbox: tree: Mozilla
|
||||
tinderbox: builddate: 900002087
|
||||
tinderbox: status: success
|
||||
tinderbox: build: IRIX 6.3 Depend
|
||||
tinderbox: errorparser: unix
|
||||
tinderbox: buildfamily: unix
|
||||
|
||||
594
mozilla/webtools/tinderbox/examples/build-moz-smoke.pl
Executable file
594
mozilla/webtools/tinderbox/examples/build-moz-smoke.pl
Executable file
@@ -0,0 +1,594 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
require 5.000;
|
||||
|
||||
use Sys::Hostname;
|
||||
use POSIX "sys_wait_h";
|
||||
use Cwd;
|
||||
|
||||
$Version = "1.000";
|
||||
|
||||
sub InitVars {
|
||||
|
||||
# PLEASE FILL THIS IN WITH YOUR PROPER EMAIL ADDRESS
|
||||
$BuildAdministrator = "$ENV{'USER'}\@$ENV{'HOST'}";
|
||||
|
||||
#Default values of cmdline opts
|
||||
$BuildDepend = 1; #depend or clobber
|
||||
$ReportStatus = 1; # Send results to server or not
|
||||
$BuildOnce = 0; # Build once, don't send results to server
|
||||
$BuildClassic = 0; # Build classic source
|
||||
|
||||
#relative path to binary
|
||||
$BinaryName{'x'} = 'mozilla-export';
|
||||
$BinaryName{'qt'} = 'qtmozilla-export';
|
||||
$BinaryName{'gnome'} = 'gnuzilla-export';
|
||||
$BinaryName{'webshell'} = '/webshell/tests/viewer/viewer';
|
||||
|
||||
# Set these to what makes sense for your system
|
||||
$cpus = 1;
|
||||
$Make = 'gmake'; # Must be gnu make
|
||||
$mail = '/bin/mail';
|
||||
$Autoconf = 'autoconf -l build/autoconf';
|
||||
$CVS = 'cvs -z3';
|
||||
$CVSCO = 'co -P';
|
||||
|
||||
# Set these proper values for your tinderbox server
|
||||
$Tinderbox_server = 'tinderbox-daemon\@cvs-mirror.mozilla.org';
|
||||
#$Tinderbox_server = 'external-tinderbox-incoming\@tinderbox.seawood.org';
|
||||
|
||||
# These shouldn't really need to be changed
|
||||
$BuildSleep = 10; # Minimum wait period from start of build to start
|
||||
# of next build in minutes
|
||||
$BuildTree = 'SeaMonkey';
|
||||
$BuildTag = '';
|
||||
$BuildName = '';
|
||||
$TopLevel = '.';
|
||||
$Topsrcdir = 'mozilla';
|
||||
$BuildObjName = '';
|
||||
$BuildConfigDir = 'mozilla/config';
|
||||
$ClobberStr = 'realclean';
|
||||
$ConfigureEnvArgs = 'CFLAGS=-pipe CXXFLAGS=-pipe';
|
||||
#$ConfigureEnvArgs = '';
|
||||
$ConfigureArgs = "--with-nspr=/usr/local/nspr --cache-file=/dev/null --with-static-gtk --enable-editor";
|
||||
$ConfigGuess = './build/autoconf/config.guess';
|
||||
$Logfile = '${BuildDir}.log';
|
||||
} #EndSub-InitVars
|
||||
|
||||
sub ConditionalArgs {
|
||||
if ( $BuildClassic ) {
|
||||
$FE = 'x';
|
||||
$ConfigureArgs .= " --enable-fe=$FE";
|
||||
# $BuildTree = 'raptor';
|
||||
$BuildModule = 'Raptor';
|
||||
$BuildTag = ''
|
||||
if ($BuildTag eq '');
|
||||
$TopLevel = "mozilla-classic";
|
||||
} else {
|
||||
# $BuildTree = 'raptor';
|
||||
# $Toolkit = 'gtk';
|
||||
$FE = 'webshell';
|
||||
# $BuildModule = 'Raptor';
|
||||
$BuildModule = 'SeaMonkeyAll';
|
||||
# $ConfigureArgs .= " --enable-toolkit=$Toolkit";
|
||||
}
|
||||
$CVSCO .= " -r $BuildTag" if ( $BuildTag ne '');
|
||||
}
|
||||
sub SetupEnv {
|
||||
umask(0);
|
||||
$ENV{"CVSROOT"} = ':pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot';
|
||||
$ENV{"LD_LIBRARY_PATH"} = '/usr/local/nspr:/builds/tinderbox/SeaMonkey/Linux_2.0.34_clobber/mozilla/obj-i586-pc-linux-gnu/dist/bin:/usr/lib/png:/usr/local/lib';
|
||||
$ENV{"DISPLAY"} = 'crucible.mcom.com:0.0';
|
||||
} #EndSub-SetupEnv
|
||||
|
||||
sub SetupPath {
|
||||
my($Path);
|
||||
$Path = $ENV{PATH};
|
||||
print "Path before: $Path\n";
|
||||
|
||||
if ( $OS eq 'SunOS' ) {
|
||||
$ENV{'PATH'} = '/usr/ccs/bin:' . $ENV{'PATH'};
|
||||
}
|
||||
|
||||
$Path = $ENV{PATH};
|
||||
print "Path After: $Path\n";
|
||||
} #EndSub-SetupPath
|
||||
|
||||
##########################################################################
|
||||
# NO USER CONFIGURABLE PIECES BEYOND THIS POINT #
|
||||
##########################################################################
|
||||
|
||||
sub GetSystemInfo {
|
||||
|
||||
$OS = `uname -s`;
|
||||
$OSVer = `uname -r`;
|
||||
|
||||
chop($OS, $OSVer);
|
||||
|
||||
if ( $OS eq 'AIX' ) {
|
||||
$OSVer = `uname -v`;
|
||||
chop($OSVer);
|
||||
$OSVer = $OSVer . "." . `uname -r`;
|
||||
chop($OSVer);
|
||||
}
|
||||
|
||||
if ( $OS eq 'IRIX64' ) {
|
||||
$OS = 'IRIX';
|
||||
}
|
||||
|
||||
if ( $OS eq 'SCO_SV' ) {
|
||||
$OS = 'SCOOS';
|
||||
$OSVer = '5.0';
|
||||
}
|
||||
|
||||
my $host, $myhost = hostname;
|
||||
chomp($myhost);
|
||||
($host, $junk) = split(/\./, $myhost);
|
||||
|
||||
$BuildName = "";
|
||||
|
||||
if ( "$host" ne "" ) {
|
||||
$BuildName = $host . ' ';
|
||||
}
|
||||
$BuildName .= $OS . ' ' . $OSVer . ' ' . ($BuildDepend?'Depend':'Clobber');
|
||||
$DirName = $OS . '_' . $OSVer . '_' . ($BuildDepend?'depend':'clobber');
|
||||
|
||||
$RealOS = $OS;
|
||||
$RealOSVer = $OSVer;
|
||||
|
||||
if ( $OS eq 'HP-UX' ) {
|
||||
$RealOSVer = substr($OSVer,0,4);
|
||||
}
|
||||
|
||||
if ( $OS eq 'Linux' ) {
|
||||
$RealOSVer = substr($OSVer,0,3);
|
||||
}
|
||||
|
||||
if ($BuildClassic) {
|
||||
$logfile = "${DirName}-classic.log";
|
||||
} else {
|
||||
$logfile = "${DirName}.log";
|
||||
}
|
||||
} #EndSub-GetSystemInfo
|
||||
|
||||
sub BuildIt {
|
||||
my ($fe, @felist, $EarlyExit, $LastTime, $StartTimeStr);
|
||||
|
||||
mkdir("$DirName", 0777);
|
||||
chdir("$DirName") || die "Couldn't enter $DirName";
|
||||
|
||||
$StartDir = getcwd();
|
||||
$LastTime = 0;
|
||||
|
||||
print "Starting dir is : $StartDir\n";
|
||||
|
||||
$EarlyExit = 0;
|
||||
|
||||
while ( ! $EarlyExit ) {
|
||||
chdir("$StartDir");
|
||||
if ( time - $LastTime < (60 * $BuildSleep) ) {
|
||||
$SleepTime = (60 * $BuildSleep) - (time - $LastTime);
|
||||
print "\n\nSleeping $SleepTime seconds ...\n";
|
||||
sleep($SleepTime);
|
||||
}
|
||||
|
||||
$LastTime = time;
|
||||
|
||||
$StartTime = time - 60 * 10;
|
||||
$StartTimeStr = &CVSTime($StartTime);
|
||||
|
||||
&StartBuild if ($ReportStatus);
|
||||
$CurrentDir = getcwd();
|
||||
if ( $CurrentDir ne $StartDir ) {
|
||||
print "startdir: $StartDir, curdir $CurrentDir\n";
|
||||
die "curdir != startdir";
|
||||
}
|
||||
|
||||
$BuildDir = $CurrentDir;
|
||||
|
||||
unlink( "$logfile" );
|
||||
|
||||
print "opening $logfile\n";
|
||||
open( LOG, ">$logfile" ) || print "can't open $?\n";
|
||||
print LOG "current dir is -- $hostname:$CurrentDir\n";
|
||||
print LOG "Build Administrator is $BuildAdministrator\n";
|
||||
&PrintEnv;
|
||||
|
||||
$BuildStatus = 0;
|
||||
|
||||
mkdir($TopLevel, 0777);
|
||||
chdir($TopLevel) || die "chdir($TopLevel): $!\n";
|
||||
|
||||
if ( $BuildClassic ) {
|
||||
print"$CVS $CVSCO $BuildModule\n";
|
||||
print LOG "$CVS $CVSCO $BuildModule\n";
|
||||
open (PULL, "$CVS $CVSCO $BuildModule 2>&1 |") || die "open: $!\n";
|
||||
} else {
|
||||
# print "$CVS $CVSCO mozilla/nglayout.mk\n";
|
||||
# print LOG "$CVS $CVSCO mozilla/nglayout.mk\n";
|
||||
# open (PULL, "$CVS $CVSCO mozilla/nglayout.mk 2>&1 |") || die "open: $!\n";
|
||||
print "$CVS $CVSCO mozilla/client.mk\n";
|
||||
print LOG "$CVS $CVSCO mozilla/client.mk\n";
|
||||
open (PULL, "$CVS $CVSCO mozilla/client.mk 2>&1 |") || die "open: $!\n";
|
||||
}
|
||||
while (<PULL>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(PULL);
|
||||
|
||||
# Move to topsrcdir
|
||||
#chdir($Topsrcdir) || die "chdir($Topsrcdir): $!\n";
|
||||
|
||||
|
||||
# Do a separate checkout with toplevel makefile
|
||||
if (! $BuildClassic) {
|
||||
# print LOG "$Make -f nglayout.mk pull_all CVSCO='$CVS $CVSCO'|\n";
|
||||
# open (PULLALL, "$Make -f nglayout.mk pull_all CVSCO='$CVS $CVSCO' |\n");
|
||||
print LOG "$Make -f mozilla/client.mk checkout CVSCO='$CVS $CVSCO'|\n";
|
||||
open (PULLALL, "$Make -f mozilla/client.mk checkout CVSCO='$CVS $CVSCO' |\n");
|
||||
while (<PULLALL>) {
|
||||
print LOG $_;
|
||||
print $_;
|
||||
}
|
||||
close(PULLALL);
|
||||
}
|
||||
|
||||
chdir($Topsrcdir) || die "chdir($Topsrcdir): $!\n";
|
||||
|
||||
print LOG "$Autoconf\n";
|
||||
open (AUTOCONF, "$Autoconf 2>&1 | ") || die "$Autoconf: $!\n";
|
||||
while (<AUTOCONF>) {
|
||||
print LOG $_;
|
||||
print $_;
|
||||
}
|
||||
close(AUTOCONF);
|
||||
|
||||
print LOG "$ConfigGuess\n";
|
||||
$BuildObjName = "obj-";
|
||||
open (GETOBJ, "$ConfigGuess 2>&1 |") || die "$ConfigGuess: $!\n";
|
||||
while (<GETOBJ>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
chomp($BuildObjName .= $_);
|
||||
}
|
||||
close (GETOBJ);
|
||||
|
||||
mkdir($BuildObjName, 0777);
|
||||
chdir($BuildObjName) || die "chdir($BuildObjName): $!\n";
|
||||
|
||||
print LOG "$ConfigureEnvArgs ../configure $ConfigureArgs\n";
|
||||
open (CONFIGURE, "$ConfigureEnvArgs ../configure $ConfigureArgs 2>&1 |") || die "../configure: $!\n";
|
||||
while (<CONFIGURE>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(CONFIGURE);
|
||||
|
||||
# if we are building depend, rebuild dependencies
|
||||
|
||||
if ($BuildDepend) {
|
||||
print LOG "$Make MAKE='$Make -j $cpus' depend 2>&1 |\n";
|
||||
open ( MAKEDEPEND, "$Make MAKE='$Make -j $cpus' depend 2>&1 |\n");
|
||||
while ( <MAKEDEPEND> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close (MAKEDEPEND);
|
||||
system("rm -rf dist");
|
||||
|
||||
} else {
|
||||
# Building clobber
|
||||
print LOG "$Make MAKE='$Make -j $cpus' $ClobberStr 2>&1 |\n";
|
||||
open( MAKECLOBBER, "$Make MAKE='$Make -j $cpus' $ClobberStr 2>&1 |");
|
||||
while ( <MAKECLOBBER> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( MAKECLOBBER );
|
||||
}
|
||||
|
||||
@felist = split(/,/, $FE);
|
||||
|
||||
foreach $fe ( @felist ) {
|
||||
if (&BinaryExists($fe)) {
|
||||
print LOG "deleting existing binary\n";
|
||||
&DeleteBinary($fe);
|
||||
}
|
||||
}
|
||||
|
||||
if ($BuildClassic) {
|
||||
# Build the BE only
|
||||
print LOG "$Make MAKE='$Make -j $cpus' MOZ_FE= 2>&1 |\n";
|
||||
open( BEBUILD, "$Make MAKE='$Make -j $cpus' MOZ_FE= 2>&1 |");
|
||||
|
||||
while ( <BEBUILD> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( BEBUILD );
|
||||
|
||||
foreach $fe ( @felist ) {
|
||||
# Now build each front end
|
||||
print LOG "$Make MAKE='$Make -j $cpus' -C cmd/${fe}fe 2>&1 |\n";
|
||||
open(FEBUILD, "$Make MAKE='$Make -j $cpus' -C cmd/${fe}fe 2>&1 |\n");
|
||||
while (<FEBUILD>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(FEBUILD);
|
||||
}
|
||||
} else {
|
||||
print LOG "$Make MAKE='$Make -j $cpus' 2>&1 |\n";
|
||||
open(BUILD, "$Make MAKE='$Make -j $cpus' 2>&1 |\n");
|
||||
while (<BUILD>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(BUILD);
|
||||
}
|
||||
|
||||
foreach $fe (@felist) {
|
||||
if (&BinaryExists($fe)) {
|
||||
print LOG "export binary exists, build successful. Testing...\n";
|
||||
#return 0 if no problem, else 333 for a runtime error
|
||||
$BuildStatus = &RunSmokeTest($fe);
|
||||
}
|
||||
else {
|
||||
print LOG "export binary missing, build FAILED\n";
|
||||
$BuildStatus = 666;
|
||||
}
|
||||
|
||||
if ( $BuildStatus == 0 ) {
|
||||
$BuildStatusStr = 'success';
|
||||
}
|
||||
elsif ( $BuildStatus == 333 ) {
|
||||
$BuildStatusStr = 'testfailed';
|
||||
}
|
||||
else {
|
||||
$BuildStatusStr = 'busted';
|
||||
}
|
||||
# replaced by above lines
|
||||
# $BuildStatusStr = ( $BuildStatus ? 'busted' : 'success' );
|
||||
|
||||
print LOG "tinderbox: tree: $BuildTree\n";
|
||||
print LOG "tinderbox: builddate: $StartTime\n";
|
||||
print LOG "tinderbox: status: $BuildStatusStr\n";
|
||||
print LOG "tinderbox: build: $BuildName $fe\n";
|
||||
print LOG "tinderbox: errorparser: unix\n";
|
||||
print LOG "tinderbox: buildfamily: unix\n";
|
||||
print LOG "tinderbox: END\n";
|
||||
}
|
||||
close(LOG);
|
||||
chdir("$StartDir");
|
||||
|
||||
# this fun line added on 2/5/98. do not remove. Translated to english,
|
||||
# that's "take any line longer than 1000 characters, and split it into less
|
||||
# than 1000 char lines. If any of the resulting lines is
|
||||
# a dot on a line by itself, replace that with a blank line."
|
||||
# This is to prevent cases where a <cr>.<cr> occurs in the log file. Sendmail
|
||||
# interprets that as the end of the mail, and truncates the log before
|
||||
# it gets to Tinderbox. (terry weismann, chris yeh)
|
||||
#
|
||||
# This was replaced by a perl 'port' of the above, writen by
|
||||
# preed@netscape.com; good things: no need for system() call, and now it's
|
||||
# all in perl, so we don't have to do OS checking like before.
|
||||
|
||||
open(LOG, "$logfile") || die "Couldn't open logfile: $!\n";
|
||||
open(OUTLOG, ">${logfile}.last") || die "Couldn't open logfile: $!\n";
|
||||
|
||||
while (<LOG>) {
|
||||
$q = 0;
|
||||
|
||||
for (;;) {
|
||||
$val = $q * 1000;
|
||||
$Output = substr($_, $val, 1000);
|
||||
|
||||
last if $Output eq undef;
|
||||
|
||||
$Output =~ s/^\.$//g;
|
||||
$Output =~ s/\n//g;
|
||||
print OUTLOG "$Output\n";
|
||||
$q++;
|
||||
} #EndFor
|
||||
|
||||
} #EndWhile
|
||||
|
||||
close(LOG);
|
||||
close(OUTLOG);
|
||||
|
||||
system( "$mail $Tinderbox_server < ${logfile}.last" )
|
||||
if ($ReportStatus );
|
||||
unlink("$logfile");
|
||||
|
||||
# if this is a test run, set early_exit to 0.
|
||||
#This mean one loop of execution
|
||||
$EarlyExit++ if ($BuildOnce);
|
||||
}
|
||||
|
||||
} #EndSub-BuildIt
|
||||
|
||||
sub CVSTime {
|
||||
my($StartTimeArg) = @_;
|
||||
my($RetTime, $StartTimeArg, $sec, $minute, $hour, $mday, $mon, $year);
|
||||
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime($StartTimeArg);
|
||||
$mon++; # month is 0 based.
|
||||
|
||||
sprintf("%02d/%02d/%02d %02d:%02d:00", $mon,$mday,$year,$hour,$minute );
|
||||
}
|
||||
|
||||
sub StartBuild {
|
||||
|
||||
my($fe, @felist);
|
||||
|
||||
@felist = split(/,/, $FE);
|
||||
|
||||
# die "SERVER: " . $Tinderbox_server . "\n";
|
||||
open( LOG, "|$mail $Tinderbox_server" );
|
||||
foreach $fe ( @felist ) {
|
||||
print LOG "\n";
|
||||
print LOG "tinderbox: tree: $BuildTree\n";
|
||||
print LOG "tinderbox: builddate: $StartTime\n";
|
||||
print LOG "tinderbox: status: building\n";
|
||||
print LOG "tinderbox: build: $BuildName $fe\n";
|
||||
print LOG "tinderbox: errorparser: unix\n";
|
||||
print LOG "tinderbox: buildfamily: unix\n";
|
||||
print LOG "tinderbox: END\n";
|
||||
print LOG "\n";
|
||||
}
|
||||
close( LOG );
|
||||
}
|
||||
|
||||
# check for the existence of the binary
|
||||
sub BinaryExists {
|
||||
my($fe) = @_;
|
||||
my($Binname);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
if ($BuildClassic) {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/'. $BuildObjName . "/cmd/${fe}fe/" . $BinaryName{"$fe"};
|
||||
} else {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
}
|
||||
print LOG $BinName . "\n";
|
||||
if ((-e $BinName) && (-x $BinName) && (-s $BinName)) {
|
||||
1;
|
||||
}
|
||||
else {
|
||||
0;
|
||||
}
|
||||
}
|
||||
|
||||
sub DeleteBinary {
|
||||
my($fe) = @_;
|
||||
my($BinName);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
if ($BuildClassic) {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . "/cmd/${fe}fe/" . $BinaryName{"$fe"};
|
||||
} else {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
}
|
||||
print LOG "unlinking $BinName\n";
|
||||
unlink ($BinName) || print LOG "unlinking $BinName failed\n";
|
||||
}
|
||||
|
||||
sub ParseArgs {
|
||||
my($i, $manArg);
|
||||
|
||||
if( @ARGV == 0 ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
$i = 0;
|
||||
$manArg = 0;
|
||||
while( $i < @ARGV ) {
|
||||
if ($ARGV[$i] eq '--depend') {
|
||||
$BuildDepend = 1;
|
||||
$manArg++;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--clobber') {
|
||||
$BuildDepend = 0;
|
||||
$manArg++;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--once' ) {
|
||||
$BuildOnce = 1;
|
||||
#$ReportStatus = 0;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--classic') {
|
||||
$BuildClassic = 1;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--noreport') {
|
||||
$ReportStatus = 0;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--version' || $ARGV[$i] eq '-v') {
|
||||
die "$0: version $Version\n";
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-tag' ) {
|
||||
$i++;
|
||||
$BuildTag = $ARGV[$i];
|
||||
if ( $BuildTag eq '' || $BuildTag eq '-t') {
|
||||
&PrintUsage;
|
||||
}
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-t' ) {
|
||||
$i++;
|
||||
$BuildTree = $ARGV[$i];
|
||||
if ( $BuildTree eq '' ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
} else {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
$i++;
|
||||
} #EndWhile
|
||||
|
||||
if ( $BuildTree =~ /^\s+$/i ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
if ($BuildDepend eq undef) {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
&PrintUsage if (! $manArg );
|
||||
|
||||
} #EndSub-ParseArgs
|
||||
|
||||
sub PrintUsage {
|
||||
die "usage: $0 [--depend | --clobber] [-v | --version ] [--once --classic --noreport -tag TREETAG -t TREENAME ]\n";
|
||||
}
|
||||
|
||||
sub PrintEnv {
|
||||
my ($key);
|
||||
foreach $key (keys %ENV) {
|
||||
print LOG "$key = $ENV{$key}\n";
|
||||
print "$key = $ENV{$key}\n";
|
||||
}
|
||||
} #EndSub-PrintEnv
|
||||
|
||||
sub RunSmokeTest {
|
||||
my($fe) = @_;
|
||||
my($Binary);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
$Binary = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
print LOG $BinName . "\n";
|
||||
|
||||
$waittime = 30;
|
||||
|
||||
$pid = fork;
|
||||
|
||||
exec $Binary if !$pid;
|
||||
|
||||
# parent - wait $waittime seconds then check on child
|
||||
sleep $waittime;
|
||||
$status = waitpid $pid, WNOHANG();
|
||||
if ($status != 0) {
|
||||
print LOG "$BinName has crashed or quit. Turn the tree orange now.\n";
|
||||
return 333;
|
||||
}
|
||||
|
||||
print LOG "Success! $BinName is still running. Killing..\n";
|
||||
# try to kill 3 times, then try a kill -9
|
||||
for ($i=0 ; $i<3 ; $i++) {
|
||||
kill 'TERM',$pid,;
|
||||
# give it 3 seconds to actually die
|
||||
sleep 3;
|
||||
$status = waitpid $pid, WNOHANG();
|
||||
last if ($status != 0);
|
||||
}
|
||||
return 0;
|
||||
} #EndSub-RunSmokeTest
|
||||
|
||||
# Main function
|
||||
&InitVars;
|
||||
&ParseArgs;
|
||||
&ConditionalArgs;
|
||||
&GetSystemInfo;
|
||||
&SetupEnv;
|
||||
&SetupPath;
|
||||
&BuildIt;
|
||||
|
||||
1;
|
||||
63
mozilla/webtools/tinderbox/examples/buildit.config
Executable file
63
mozilla/webtools/tinderbox/examples/buildit.config
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
sub InitVars {
|
||||
|
||||
#initialize variables
|
||||
#$binary_name = '/netscape-export';
|
||||
$BinaryName = '/mozilla-export';
|
||||
$BuildDepend = 1; #depend or clobber
|
||||
$BuildTree = '';
|
||||
$BuildTag = '';
|
||||
$BuildName = '';
|
||||
#$BuildContinue = 0;
|
||||
$TopLevel = 'mozilla/';
|
||||
$BuildObjName = '';
|
||||
$BuildSleep = 10;
|
||||
$BuildUnixclasses = 0;
|
||||
$EarlyExit = 1;
|
||||
$BuildStartDir = 'ns/';
|
||||
$BuildConfigDir = 'mozilla/config';
|
||||
|
||||
} #EndSub-InitVars
|
||||
|
||||
sub SetupEnv {
|
||||
|
||||
umask(0);
|
||||
$ENV{'MOZILLA_CLIENT'} = 1;
|
||||
$ENV{'NETSCAPE_HIERARCHY'} = 1;
|
||||
$ENV{'BUILD_OFFICIAL'} = 1;
|
||||
$ENV{'NSPR20'} = 1;
|
||||
$ENV{'AWT_11'} = 1;
|
||||
$ENV{'MOZ_SECURITY'} = 1;
|
||||
$ENV{"CVSROOT"} = '/m/src';
|
||||
$ENV{"MAKE"} = 'gmake -e';
|
||||
$ENV{'MOZ_MEDIUM'} = 1;
|
||||
$ENV{'NO_MDUPDATE'} = 1;
|
||||
$ENV{'EDITOR'} = 1;
|
||||
|
||||
} #EndSub-SetupEnv
|
||||
|
||||
sub SetupPath {
|
||||
|
||||
my($Path);
|
||||
$Path = $ENV{PATH};
|
||||
print "Path before: $Path\n";
|
||||
$ENV{'PATH'} = '/tools/ns/bin:/tools/contrib/bin:/usr/local/bin:/usr/sbin:/usr/bsd:/sbin:/usr/bin:/bin:/usr/bin/X11:/usr/etc:/usr/hosts:/usr/ucb:';
|
||||
|
||||
# This won't work on x86 or sunos4 systems....
|
||||
if ( $OS eq 'SunOS' ) {
|
||||
$ENV{'PATH'} = '/usr/ccs/bin:/tools/ns/soft/gcc-2.6.3/run/default/sparc_sun_solaris2.4/bin:' . $ENV{'PATH'};
|
||||
$ENV{'NO_MDUPDATE'} = 1;
|
||||
}
|
||||
|
||||
if ( $OS eq 'AIX' ) {
|
||||
$ENV{'PATH'} = $ENV{'PATH'} . '/usr/lpp/xlC/bin:/usr/local-aix/bin:';
|
||||
}
|
||||
|
||||
$Path = $ENV{PATH};
|
||||
print "Path After: $Path\n";
|
||||
|
||||
} #EndSub-SetupPath
|
||||
|
||||
|
||||
1;
|
||||
548
mozilla/webtools/tinderbox/examples/mozilla-unix.pl
Executable file
548
mozilla/webtools/tinderbox/examples/mozilla-unix.pl
Executable file
@@ -0,0 +1,548 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
require 5.000;
|
||||
|
||||
use Sys::Hostname;
|
||||
use Cwd;
|
||||
|
||||
$Version = "1.000";
|
||||
|
||||
sub InitVars {
|
||||
|
||||
# PLEASE FILL THIS IN WITH YOUR PROPER EMAIL ADDRESS
|
||||
$BuildAdministrator = "$ENV{'USER'}\@$ENV{'HOST'}";
|
||||
|
||||
#Default values of cmdline opts
|
||||
$BuildDepend = 1; #depend or clobber
|
||||
$ReportStatus = 1; # Send results to server or not
|
||||
$BuildOnce = 0; # Build once, don't send results to server
|
||||
$BuildClassic = 0; # Build classic source
|
||||
|
||||
#relative path to binary
|
||||
$BinaryName{'x'} = 'mozilla-export';
|
||||
$BinaryName{'qt'} = 'qtmozilla-export';
|
||||
$BinaryName{'gnome'} = 'gnuzilla-export';
|
||||
$BinaryName{'webshell'} = '/webshell/tests/viewer/viewer';
|
||||
$BinaryName{'xpfe'} = '/xpfe/xpviewer/src/xpviewer';
|
||||
|
||||
# Set these to what makes sense for your system
|
||||
$cpus = 1;
|
||||
$Make = 'gmake'; # Must be gnu make
|
||||
$mail = '/bin/mail';
|
||||
$Autoconf = 'autoconf -l build/autoconf';
|
||||
$CVS = 'cvs -z3';
|
||||
$CVSCO = 'co -P';
|
||||
|
||||
# Set these proper values for your tinderbox server
|
||||
$Tinderbox_server = 'tinderbox-daemon\@warp.mcom.com';
|
||||
#$Tinderbox_server = 'external-tinderbox-incoming\@tinderbox.seawood.org';
|
||||
|
||||
# These shouldn't really need to be changed
|
||||
$BuildSleep = 10; # Minimum wait period from start of build to start
|
||||
# of next build in minutes
|
||||
$BuildTree = 'raptor';
|
||||
$BuildTag = '';
|
||||
$BuildName = '';
|
||||
$TopLevel = '.';
|
||||
$Topsrcdir = 'mozilla';
|
||||
$BuildObjName = '';
|
||||
$BuildConfigDir = 'mozilla/config';
|
||||
$ClobberStr = 'realclean';
|
||||
$ConfigureEnvArgs = 'CFLAGS=-pipe CXXFLAGS=-pipe';
|
||||
#$ConfigureEnvArgs = '';
|
||||
$ConfigureArgs = "--cache-file=/dev/null";
|
||||
$ConfigGuess = './build/autoconf/config.guess';
|
||||
$Logfile = '${BuildDir}.log';
|
||||
} #EndSub-InitVars
|
||||
|
||||
sub ConditionalArgs {
|
||||
if ( $BuildClassic ) {
|
||||
$FE = 'x';
|
||||
$ConfigureArgs .= " --enable-fe=$FE";
|
||||
$BuildTree = 'raptor';
|
||||
$BuildModule = 'Raptor';
|
||||
$BuildTag = ''
|
||||
if ($BuildTag eq '');
|
||||
$TopLevel = "mozilla-classic";
|
||||
} else {
|
||||
$BuildTree = 'raptor';
|
||||
# $Toolkit = 'gtk';
|
||||
$FE = 'webshell,xpfe';
|
||||
$BuildModule = 'Raptor';
|
||||
# $ConfigureArgs .= " --enable-toolkit=$Toolkit";
|
||||
}
|
||||
$CVSCO .= " -r $BuildTag" if ( $BuildTag ne '');
|
||||
}
|
||||
sub SetupEnv {
|
||||
umask(0);
|
||||
$ENV{"CVSROOT"} = ':pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot';
|
||||
} #EndSub-SetupEnv
|
||||
|
||||
sub SetupPath {
|
||||
my($Path);
|
||||
$Path = $ENV{PATH};
|
||||
print "Path before: $Path\n";
|
||||
|
||||
if ( $OS eq 'SunOS' ) {
|
||||
$ENV{'PATH'} = '/usr/ccs/bin:' . $ENV{'PATH'};
|
||||
}
|
||||
|
||||
$Path = $ENV{PATH};
|
||||
print "Path After: $Path\n";
|
||||
} #EndSub-SetupPath
|
||||
|
||||
##########################################################################
|
||||
# NO USER CONFIGURABLE PIECES BEYOND THIS POINT #
|
||||
##########################################################################
|
||||
|
||||
sub GetSystemInfo {
|
||||
|
||||
$OS = `uname -s`;
|
||||
$OSVer = `uname -r`;
|
||||
|
||||
chop($OS, $OSVer);
|
||||
|
||||
if ( $OS eq 'AIX' ) {
|
||||
$OSVer = `uname -v`;
|
||||
chop($OSVer);
|
||||
$OSVer = $OSVer . "." . `uname -r`;
|
||||
chop($OSVer);
|
||||
}
|
||||
|
||||
if ( $OS eq 'IRIX64' ) {
|
||||
$OS = 'IRIX';
|
||||
}
|
||||
|
||||
if ( $OS eq 'SCO_SV' ) {
|
||||
$OS = 'SCOOS';
|
||||
$OSVer = '5.0';
|
||||
}
|
||||
|
||||
my $host, $myhost = hostname;
|
||||
chomp($myhost);
|
||||
($host, $junk) = split(/\./, $myhost);
|
||||
|
||||
$BuildName = "";
|
||||
|
||||
if ( "$host" ne "" ) {
|
||||
$BuildName = $host . ' ';
|
||||
}
|
||||
$BuildName .= $OS . ' ' . $OSVer . ' ' . ($BuildDepend?'Depend':'Clobber');
|
||||
$DirName = $OS . '_' . $OSVer . '_' . ($BuildDepend?'depend':'clobber');
|
||||
|
||||
$RealOS = $OS;
|
||||
$RealOSVer = $OSVer;
|
||||
|
||||
if ( $OS eq 'HP-UX' ) {
|
||||
$RealOSVer = substr($OSVer,0,4);
|
||||
}
|
||||
|
||||
if ( $OS eq 'Linux' ) {
|
||||
$RealOSVer = substr($OSVer,0,3);
|
||||
}
|
||||
|
||||
if ($BuildClassic) {
|
||||
$logfile = "${DirName}-classic.log";
|
||||
} else {
|
||||
$logfile = "${DirName}.log";
|
||||
}
|
||||
} #EndSub-GetSystemInfo
|
||||
|
||||
sub BuildIt {
|
||||
my ($fe, @felist, $EarlyExit, $LastTime, $StartTimeStr);
|
||||
|
||||
mkdir("$DirName", 0777);
|
||||
chdir("$DirName") || die "Couldn't enter $DirName";
|
||||
|
||||
$StartDir = getcwd();
|
||||
$LastTime = 0;
|
||||
|
||||
print "Starting dir is : $StartDir\n";
|
||||
|
||||
$EarlyExit = 0;
|
||||
|
||||
while ( ! $EarlyExit ) {
|
||||
chdir("$StartDir");
|
||||
if ( time - $LastTime < (60 * $BuildSleep) ) {
|
||||
$SleepTime = (60 * $BuildSleep) - (time - $LastTime);
|
||||
print "\n\nSleeping $SleepTime seconds ...\n";
|
||||
sleep($SleepTime);
|
||||
}
|
||||
|
||||
$LastTime = time;
|
||||
|
||||
$StartTime = time - 60 * 10;
|
||||
$StartTimeStr = &CVSTime($StartTime);
|
||||
|
||||
&StartBuild if ($ReportStatus);
|
||||
$CurrentDir = getcwd();
|
||||
if ( $CurrentDir ne $StartDir ) {
|
||||
print "startdir: $StartDir, curdir $CurrentDir\n";
|
||||
die "curdir != startdir";
|
||||
}
|
||||
|
||||
$BuildDir = $CurrentDir;
|
||||
|
||||
unlink( "$logfile" );
|
||||
|
||||
print "opening $logfile\n";
|
||||
open( LOG, ">$logfile" ) || print "can't open $?\n";
|
||||
print LOG "current dir is -- $hostname:$CurrentDir\n";
|
||||
print LOG "Build Administrator is $BuildAdministrator\n";
|
||||
&PrintEnv;
|
||||
|
||||
$BuildStatus = 0;
|
||||
|
||||
mkdir($TopLevel, 0777);
|
||||
chdir($TopLevel) || die "chdir($TopLevel): $!\n";
|
||||
|
||||
if ( $BuildClassic ) {
|
||||
print"$CVS $CVSCO $BuildModule\n";
|
||||
print LOG "$CVS $CVSCO $BuildModule\n";
|
||||
open (PULL, "$CVS $CVSCO $BuildModule 2>&1 |") || die "open: $!\n";
|
||||
} else {
|
||||
# print "$CVS $CVSCO mozilla/nglayout.mk\n";
|
||||
# print LOG "$CVS $CVSCO mozilla/nglayout.mk\n";
|
||||
# open (PULL, "$CVS $CVSCO mozilla/nglayout.mk 2>&1 |") || die "open: $!\n";
|
||||
print "$CVS $CVSCO mozilla/client.mk\n";
|
||||
print LOG "$CVS $CVSCO mozilla/client.mk\n";
|
||||
open (PULL, "$CVS $CVSCO mozilla/client.mk 2>&1 |") || die "open: $!\n";
|
||||
}
|
||||
while (<PULL>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(PULL);
|
||||
|
||||
# Move to topsrcdir
|
||||
#chdir($Topsrcdir) || die "chdir($Topsrcdir): $!\n";
|
||||
|
||||
|
||||
# Do a separate checkout with toplevel makefile
|
||||
if (! $BuildClassic) {
|
||||
# print LOG "$Make -f nglayout.mk pull_all CVSCO='$CVS $CVSCO'|\n";
|
||||
# open (PULLALL, "$Make -f nglayout.mk pull_all CVSCO='$CVS $CVSCO' |\n");
|
||||
print LOG "$Make -f mozilla/client.mk checkout CVSCO='$CVS $CVSCO'|\n";
|
||||
open (PULLALL, "$Make -f mozilla/client.mk checkout CVSCO='$CVS $CVSCO' |\n");
|
||||
while (<PULLALL>) {
|
||||
print LOG $_;
|
||||
print $_;
|
||||
}
|
||||
close(PULLALL);
|
||||
}
|
||||
|
||||
chdir($Topsrcdir) || die "chdir($Topsrcdir): $!\n";
|
||||
|
||||
print LOG "$Autoconf\n";
|
||||
open (AUTOCONF, "$Autoconf 2>&1 | ") || die "$Autoconf: $!\n";
|
||||
while (<AUTOCONF>) {
|
||||
print LOG $_;
|
||||
print $_;
|
||||
}
|
||||
close(AUTOCONF);
|
||||
|
||||
print LOG "$ConfigGuess\n";
|
||||
$BuildObjName = "obj-";
|
||||
open (GETOBJ, "$ConfigGuess 2>&1 |") || die "$ConfigGuess: $!\n";
|
||||
while (<GETOBJ>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
chomp($BuildObjName .= $_);
|
||||
}
|
||||
close (GETOBJ);
|
||||
|
||||
mkdir($BuildObjName, 0777);
|
||||
chdir($BuildObjName) || die "chdir($BuildObjName): $!\n";
|
||||
|
||||
print LOG "$ConfigureEnvArgs ../configure $ConfigureArgs\n";
|
||||
open (CONFIGURE, "$ConfigureEnvArgs ../configure $ConfigureArgs 2>&1 |") || die "../configure: $!\n";
|
||||
while (<CONFIGURE>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(CONFIGURE);
|
||||
|
||||
# if we are building depend, rebuild dependencies
|
||||
|
||||
if ($BuildDepend) {
|
||||
print LOG "$Make MAKE='$Make -j $cpus' depend 2>&1 |\n";
|
||||
open ( MAKEDEPEND, "$Make MAKE='$Make -j $cpus' depend 2>&1 |\n");
|
||||
while ( <MAKEDEPEND> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close (MAKEDEPEND);
|
||||
system("rm -rf dist");
|
||||
|
||||
} else {
|
||||
# Building clobber
|
||||
print LOG "$Make MAKE='$Make -j $cpus' $ClobberStr 2>&1 |\n";
|
||||
open( MAKECLOBBER, "$Make MAKE='$Make -j $cpus' $ClobberStr 2>&1 |");
|
||||
while ( <MAKECLOBBER> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( MAKECLOBBER );
|
||||
}
|
||||
|
||||
@felist = split(/,/, $FE);
|
||||
|
||||
foreach $fe ( @felist ) {
|
||||
if (&BinaryExists($fe)) {
|
||||
print LOG "deleting existing binary\n";
|
||||
&DeleteBinary($fe);
|
||||
}
|
||||
}
|
||||
|
||||
if ($BuildClassic) {
|
||||
# Build the BE only
|
||||
print LOG "$Make MAKE='$Make -j $cpus' MOZ_FE= 2>&1 |\n";
|
||||
open( BEBUILD, "$Make MAKE='$Make -j $cpus' MOZ_FE= 2>&1 |");
|
||||
|
||||
while ( <BEBUILD> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( BEBUILD );
|
||||
|
||||
foreach $fe ( @felist ) {
|
||||
# Now build each front end
|
||||
print LOG "$Make MAKE='$Make -j $cpus' -C cmd/${fe}fe 2>&1 |\n";
|
||||
open(FEBUILD, "$Make MAKE='$Make -j $cpus' -C cmd/${fe}fe 2>&1 |\n");
|
||||
while (<FEBUILD>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(FEBUILD);
|
||||
}
|
||||
} else {
|
||||
print LOG "$Make MAKE='$Make -j $cpus' 2>&1 |\n";
|
||||
open(BUILD, "$Make MAKE='$Make -j $cpus' 2>&1 |\n");
|
||||
while (<BUILD>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(BUILD);
|
||||
}
|
||||
|
||||
foreach $fe (@felist) {
|
||||
if (&BinaryExists($fe)) {
|
||||
print LOG "export binary exists, build SUCCESSFUL!\n";
|
||||
$BuildStatus = 0;
|
||||
}
|
||||
else {
|
||||
print LOG "export binary missing, build FAILED\n";
|
||||
$BuildStatus = 666;
|
||||
}
|
||||
|
||||
print LOG "\nBuild Status = $BuildStatus\n";
|
||||
|
||||
$BuildStatusStr = ( $BuildStatus ? 'busted' : 'success' );
|
||||
|
||||
print LOG "tinderbox: tree: $BuildTree\n";
|
||||
print LOG "tinderbox: builddate: $StartTime\n";
|
||||
print LOG "tinderbox: status: $BuildStatusStr\n";
|
||||
print LOG "tinderbox: build: $BuildName $fe\n";
|
||||
print LOG "tinderbox: errorparser: unix\n";
|
||||
print LOG "tinderbox: buildfamily: unix\n";
|
||||
print LOG "tinderbox: END\n";
|
||||
}
|
||||
close(LOG);
|
||||
chdir("$StartDir");
|
||||
|
||||
# this fun line added on 2/5/98. do not remove. Translated to english,
|
||||
# that's "take any line longer than 1000 characters, and split it into less
|
||||
# than 1000 char lines. If any of the resulting lines is
|
||||
# a dot on a line by itself, replace that with a blank line."
|
||||
# This is to prevent cases where a <cr>.<cr> occurs in the log file. Sendmail
|
||||
# interprets that as the end of the mail, and truncates the log before
|
||||
# it gets to Tinderbox. (terry weismann, chris yeh)
|
||||
#
|
||||
# This was replaced by a perl 'port' of the above, writen by
|
||||
# preed@netscape.com; good things: no need for system() call, and now it's
|
||||
# all in perl, so we don't have to do OS checking like before.
|
||||
|
||||
open(LOG, "$logfile") || die "Couldn't open logfile: $!\n";
|
||||
open(OUTLOG, ">${logfile}.last") || die "Couldn't open logfile: $!\n";
|
||||
|
||||
while (<LOG>) {
|
||||
$q = 0;
|
||||
|
||||
for (;;) {
|
||||
$val = $q * 1000;
|
||||
$Output = substr($_, $val, 1000);
|
||||
|
||||
last if $Output eq undef;
|
||||
|
||||
$Output =~ s/^\.$//g;
|
||||
$Output =~ s/\n//g;
|
||||
print OUTLOG "$Output\n";
|
||||
$q++;
|
||||
} #EndFor
|
||||
|
||||
} #EndWhile
|
||||
|
||||
close(LOG);
|
||||
close(OUTLOG);
|
||||
|
||||
system( "$mail $Tinderbox_server < ${logfile}.last" )
|
||||
if ($ReportStatus );
|
||||
unlink("$logfile");
|
||||
|
||||
# if this is a test run, set early_exit to 0.
|
||||
#This mean one loop of execution
|
||||
$EarlyExit++ if ($BuildOnce);
|
||||
}
|
||||
|
||||
} #EndSub-BuildIt
|
||||
|
||||
sub CVSTime {
|
||||
my($StartTimeArg) = @_;
|
||||
my($RetTime, $StartTimeArg, $sec, $minute, $hour, $mday, $mon, $year);
|
||||
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime($StartTimeArg);
|
||||
$mon++; # month is 0 based.
|
||||
|
||||
sprintf("%02d/%02d/%02d %02d:%02d:00", $mon,$mday,$year,$hour,$minute );
|
||||
}
|
||||
|
||||
sub StartBuild {
|
||||
|
||||
my($fe, @felist);
|
||||
|
||||
@felist = split(/,/, $FE);
|
||||
|
||||
# die "SERVER: " . $Tinderbox_server . "\n";
|
||||
open( LOG, "|$mail $Tinderbox_server" );
|
||||
foreach $fe ( @felist ) {
|
||||
print LOG "\n";
|
||||
print LOG "tinderbox: tree: $BuildTree\n";
|
||||
print LOG "tinderbox: builddate: $StartTime\n";
|
||||
print LOG "tinderbox: status: building\n";
|
||||
print LOG "tinderbox: build: $BuildName $fe\n";
|
||||
print LOG "tinderbox: errorparser: unix\n";
|
||||
print LOG "tinderbox: buildfamily: unix\n";
|
||||
print LOG "tinderbox: END\n";
|
||||
print LOG "\n";
|
||||
}
|
||||
close( LOG );
|
||||
}
|
||||
|
||||
# check for the existence of the binary
|
||||
sub BinaryExists {
|
||||
my($fe) = @_;
|
||||
my($Binname);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
if ($BuildClassic) {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/'. $BuildObjName . "/cmd/${fe}fe/" . $BinaryName{"$fe"};
|
||||
} else {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
}
|
||||
print LOG $BinName . "\n";
|
||||
if ((-e $BinName) && (-x $BinName) && (-s $BinName)) {
|
||||
1;
|
||||
}
|
||||
else {
|
||||
0;
|
||||
}
|
||||
}
|
||||
|
||||
sub DeleteBinary {
|
||||
my($fe) = @_;
|
||||
my($BinName);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
if ($BuildClassic) {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . "/cmd/${fe}fe/" . $BinaryName{"$fe"};
|
||||
} else {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
}
|
||||
print LOG "unlinking $BinName\n";
|
||||
unlink ($BinName) || print LOG "unlinking $BinName failed\n";
|
||||
}
|
||||
|
||||
sub ParseArgs {
|
||||
my($i, $manArg);
|
||||
|
||||
if( @ARGV == 0 ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
$i = 0;
|
||||
$manArg = 0;
|
||||
while( $i < @ARGV ) {
|
||||
if ($ARGV[$i] eq '--depend') {
|
||||
$BuildDepend = 1;
|
||||
$manArg++;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--clobber') {
|
||||
$BuildDepend = 0;
|
||||
$manArg++;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--once' ) {
|
||||
$BuildOnce = 1;
|
||||
#$ReportStatus = 0;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--classic') {
|
||||
$BuildClassic = 1;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--noreport') {
|
||||
$ReportStatus = 0;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--version' || $ARGV[$i] eq '-v') {
|
||||
die "$0: version $Version\n";
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-tag' ) {
|
||||
$i++;
|
||||
$BuildTag = $ARGV[$i];
|
||||
if ( $BuildTag eq '' || $BuildTag eq '-t') {
|
||||
&PrintUsage;
|
||||
}
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-t' ) {
|
||||
$i++;
|
||||
$BuildTree = $ARGV[$i];
|
||||
if ( $BuildTree eq '' ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
} else {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
$i++;
|
||||
} #EndWhile
|
||||
|
||||
if ( $BuildTree =~ /^\s+$/i ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
if ($BuildDepend eq undef) {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
&PrintUsage if (! $manArg );
|
||||
|
||||
} #EndSub-ParseArgs
|
||||
|
||||
sub PrintUsage {
|
||||
die "usage: $0 [--depend | --clobber] [-v | --version ] [--once --classic --noreport -tag TREETAG -t TREENAME ]\n";
|
||||
}
|
||||
|
||||
sub PrintEnv {
|
||||
my ($key);
|
||||
foreach $key (keys %ENV) {
|
||||
print LOG "$key = $ENV{$key}\n";
|
||||
print "$key = $ENV{$key}\n";
|
||||
}
|
||||
} #EndSub-PrintEnv
|
||||
|
||||
# Main function
|
||||
&InitVars;
|
||||
&ParseArgs;
|
||||
&ConditionalArgs;
|
||||
&GetSystemInfo;
|
||||
&SetupEnv;
|
||||
&SetupPath;
|
||||
&BuildIt;
|
||||
|
||||
1;
|
||||
416
mozilla/webtools/tinderbox/examples/mozilla-windows.pl
Executable file
416
mozilla/webtools/tinderbox/examples/mozilla-windows.pl
Executable file
@@ -0,0 +1,416 @@
|
||||
#!c:/nstools/bin/perl5
|
||||
|
||||
use Cwd;
|
||||
|
||||
$build_depend=1; #depend or clobber
|
||||
$build_tree = '';
|
||||
$build_tag = '';
|
||||
$build_name = '';
|
||||
$build_continue = 0;
|
||||
$build_sleep=10;
|
||||
$no32 = 0;
|
||||
$no16 = 0;
|
||||
$original_path = $ENV{'PATH'};
|
||||
$early_exit = 1;
|
||||
$doawt11 = 0;
|
||||
|
||||
$do_clobber = '';
|
||||
$client_param = 'pull_and_build_all';
|
||||
|
||||
&parse_args;
|
||||
|
||||
if( $build_test ){
|
||||
$build_sleep=1;
|
||||
}
|
||||
|
||||
$dirname = ($build_depend?'dep':'clob');
|
||||
|
||||
|
||||
$logfile = "${dirname}.log";
|
||||
|
||||
if( $build_depend ){
|
||||
$clobber_str = 'depend';
|
||||
}
|
||||
else {
|
||||
$clobber_str = 'clobber_all';
|
||||
}
|
||||
|
||||
|
||||
mkdir("$dirname", 0777);
|
||||
chdir("$dirname") || die "couldn't cd to $dirname";
|
||||
|
||||
$start_dir = cwd;
|
||||
$last_time = 0;
|
||||
|
||||
print "starting dir is :$start_dir\n";
|
||||
|
||||
|
||||
while( $early_exit ){
|
||||
chdir("$start_dir");
|
||||
if( time - $last_time < (60 * $build_sleep) ){
|
||||
$sleep_time = (60 * $build_sleep) - (time - $last_time);
|
||||
print "\n\nSleeping $sleep_time seconds ...\n";
|
||||
sleep( $sleep_time );
|
||||
}
|
||||
$last_time = time;
|
||||
|
||||
$start_time = time-60*10;
|
||||
$start_time_str = &cvs_time( $start_time );
|
||||
# call setup_env here in the loop, to update MOZ_DATE with each pass.
|
||||
# setup_env uses start_time_str for MOZ_DATE.
|
||||
&setup_env;
|
||||
|
||||
|
||||
$cur_dir = cwd;
|
||||
|
||||
if( $cur_dir ne $start_dir ){
|
||||
print "startdir: $start_dir, curdir $cur_dir\n";
|
||||
die "curdir != startdir";
|
||||
}
|
||||
|
||||
# build 32-bit with AWT_11=1
|
||||
&setup32("1");
|
||||
if( !$no32 ){
|
||||
if( !$noawt11 ){
|
||||
&do_build(1,$do_clobber);
|
||||
}
|
||||
}
|
||||
|
||||
if ($build_test) {
|
||||
$early_exit = 0; # stops this while loop after one pass.
|
||||
}
|
||||
if( !$no16 ){
|
||||
|
||||
# build 32-bit with AWT_11=0
|
||||
# necessary before building 16-bit because 16-bit cannot use AWT 1.1 classes
|
||||
&setup32("0");
|
||||
if( !$no32 ){
|
||||
if( !$noawt11 ){
|
||||
&do_build(0,'');
|
||||
} else {
|
||||
&do_build(1,$do_clobber);
|
||||
}
|
||||
}
|
||||
|
||||
&setup16;
|
||||
|
||||
# strip_conf fails to strip any variables from the real environemnt
|
||||
# &strip_config;
|
||||
&do_build(0,'');
|
||||
# &restore_config;
|
||||
}
|
||||
}
|
||||
|
||||
sub copy_win16_dist {
|
||||
|
||||
system 'xcopy w:\ y:\ns\dist /S /E /F';
|
||||
print "COPYCOPYCOPY\n";
|
||||
|
||||
}
|
||||
|
||||
sub build_NSPR20_Win16 {
|
||||
|
||||
&start_build;
|
||||
unlink( "${logname}.last" );
|
||||
rename( "${logname}","${logname}.last");
|
||||
|
||||
print "opening ${logname}\n";
|
||||
open( LOG, ">${logname}" ) || print "can't open $?\n";
|
||||
print LOG "current dir is :$cur_dir\n";
|
||||
|
||||
&print_env;
|
||||
|
||||
chdir("$moz_src/ns/nspr20") || die "couldn't chdir to '$moz_src/ns/nspr20'";
|
||||
print LOG "gmake |\n";
|
||||
open( BUILDNSPR, "gmake 2>&1 |") || print "couldn't execute gmake\n";;
|
||||
|
||||
while( <BUILDNSPR> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close ( BUILDNSPR );
|
||||
|
||||
close( LOG );
|
||||
}
|
||||
|
||||
sub setup32 {
|
||||
local ($awt) = @_;
|
||||
|
||||
$ENV{"MOZ_BITS"} = '32';
|
||||
$ENV{"AWT_11"} = $awt;
|
||||
$doawt11 = $awt;
|
||||
|
||||
$ENV{"INCLUDE"} = "$msdev\\include;$msdev\\mfc\\include";
|
||||
$ENV{"LIB"} = "$msdev\\lib;$msdev\\mfc\\lib";
|
||||
$ENV{"PATH"} = $original_path . ";$msdev\\bin";
|
||||
$ENV{"OS_TARGET"} = 'WIN95';
|
||||
$moz_src = $ENV{'MOZ_SRC'} = $start_dir;
|
||||
$build_name = 'Win32 ' . ($build_depend?'Depend':'Clobber');
|
||||
$do_clobber = $clobber_str;
|
||||
$logname = "win32.log";
|
||||
}
|
||||
|
||||
sub setup16 {
|
||||
$moz_src = $ENV{'MOZ_SRC'} = $start_dir;
|
||||
$ENV{"MOZ_BITS"} = '16';
|
||||
# perl 5 is fucked up. you MUST set AWT_11=0. deleting the environment
|
||||
# variable doesn't work. it's removed from the environment entry, but
|
||||
# is still defined as true for a build.
|
||||
$ENV{"AWT_11"} = '0';
|
||||
$moz_src = $ENV{'MOZ_SRC'} = "$src_16_drive";
|
||||
$ENV{"OS_TARGET"} = 'WIN16';
|
||||
|
||||
$msvc_inc = "$moz_src\\ns\\msvc15\\include;$moz_src\\ns\\msvc15\\mfc\\include";
|
||||
$msvc_lib = "$msvc\\lib;$msvc\\mfc\\lib";
|
||||
$msvcpath = "$msvc\\bin;c:\\nstools\\bin;c:\\WINNT40;c:\\WINNT40\\system32;c:\\utils";
|
||||
$ENV{"MSVC_INC"} = $msvc_inc;
|
||||
$ENV{"MSVC_LIB"} = $msvc_lib;
|
||||
$ENV{"MSVCPATH"} = $msvcpath;
|
||||
|
||||
$ENV{"INCLUDE"} = $msvc_inc;
|
||||
$ENV{"LIB"} = $msvc_lib;
|
||||
$ENV{"PATH"} = $msvcpath;
|
||||
|
||||
$watcom = $ENV{"WATCOM"} = "C:\\WATCOM";
|
||||
$ENV{"EDPATH"} = "$watcom\\EDDAT";
|
||||
$ENV{"WATC_INC"} = "$watcom\\h;$watcom\\h\win;$msvc_inc";
|
||||
$ENV{"WATC_LIB"} = $msvc_lib;
|
||||
$ENV{"WATCPATH"} = "$watcom\\BINNT;$watcom\\BINW;c:\\nstools\\bin";
|
||||
|
||||
$build_name = 'Win16 ' . ($build_depend?'Depend':'Clobber');
|
||||
$do_clobber = $clobber_str;
|
||||
$logname = "win16.log";
|
||||
|
||||
system "subst l: /d";
|
||||
system "subst r: /d";
|
||||
system "subst $src_16_drive /d";
|
||||
|
||||
system "subst $src_16_drive $start_dir";
|
||||
system "subst r: $src_16_drive\\ns\\netsite\\ldap\\libraries\\msdos\\winsock";
|
||||
system "subst l: $src_16_drive\\ns\\netsite";
|
||||
}
|
||||
|
||||
sub do_build {
|
||||
local ($pull, $do_clobber) = @_;
|
||||
|
||||
&start_build;
|
||||
|
||||
print "opening ${logname}\n";
|
||||
open( LOG, ">${logname}" ) || print "can't open $?\n";
|
||||
print LOG "current dir is :$cur_dir\n";
|
||||
|
||||
&print_env;
|
||||
$build_status = 0;
|
||||
if( $pull ){
|
||||
if ( $build_tag eq '' ){
|
||||
print LOG "cvs co -D\"$start_time_str\" mozilla/client.mak 2>&1 |\n";
|
||||
open( PULL, "cvs co -D\"$start_time_str\" mozilla/client.mak 2>&1 |") || print "couldn't execute cvs\n";;
|
||||
} else{
|
||||
print LOG "cvs co -r $build_tag mozilla/client.mak 2>&1 |\n";
|
||||
open( PULL, "cvs co -r $build_tag mozilla/client.mak 2>&1 |") || print "couldn't execute cvs\n";;
|
||||
}
|
||||
|
||||
# tee the output
|
||||
while( <PULL> ){
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( PULL );
|
||||
|
||||
$build_status = $?;
|
||||
}
|
||||
|
||||
chdir("$moz_src/mozilla") || die "couldn't chdir to '$moz_src/mozilla'";
|
||||
|
||||
if( $do_clobber ne '' ){
|
||||
print LOG "nmake -f client.mak $do_clobber |\n";
|
||||
print "nmake -f client.mak $do_clobber |\n";
|
||||
open( PULL, "nmake -f client.mak $do_clobber 2>&1 |") || print "couldn't execute nmake\n";;
|
||||
|
||||
# tee the output
|
||||
while( <PULL> ){
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( PULL );
|
||||
}
|
||||
|
||||
|
||||
if (!$pull) {
|
||||
$client_param = 'build_all';
|
||||
}
|
||||
else {
|
||||
$client_param = 'pull_and_build_all';
|
||||
}
|
||||
if (!$doawt11) {
|
||||
$client_param = 'build_dist';
|
||||
}
|
||||
|
||||
print LOG "nmake -f client.mak $client_param 2>&1 |\n";
|
||||
open( BUILD, "nmake -f client.mak $client_param 2>&1 |");
|
||||
|
||||
# tee the output
|
||||
while( <BUILD> ){
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( BUILD );
|
||||
$build_status |= $?;
|
||||
|
||||
$build_status_str = ( $build_status ? 'busted' : 'success' );
|
||||
|
||||
print LOG "tinderbox: tree: $build_tree\n";
|
||||
print LOG "tinderbox: builddate: $start_time\n";
|
||||
print LOG "tinderbox: status: $build_status_str\n";
|
||||
print LOG "tinderbox: build: $build_name\n";
|
||||
print LOG "tinderbox: errorparser: windows\n";
|
||||
print LOG "tinderbox: buildfamily: windows\n";
|
||||
|
||||
close( LOG );
|
||||
chdir("$start_dir");
|
||||
system( "$nstools\\bin\\blat ${logname} -t tinderbox-daemon\@warp" );
|
||||
}
|
||||
|
||||
sub cvs_time {
|
||||
local( $ret_time );
|
||||
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime( $_[0] );
|
||||
$mon++; # month is 0 based.
|
||||
|
||||
sprintf("%02d/%02d/%02d %02d:%02d:00",
|
||||
$mon,$mday,$year,$hour,$minute );
|
||||
}
|
||||
|
||||
|
||||
sub start_build {
|
||||
open( LOG, ">>logfile" );
|
||||
print LOG "\n";
|
||||
print LOG "tinderbox: tree: $build_tree\n";
|
||||
print LOG "tinderbox: builddate: $start_time\n";
|
||||
print LOG "tinderbox: status: building\n";
|
||||
print LOG "tinderbox: build: $build_name\n";
|
||||
print LOG "tinderbox: errorparser: windows\n";
|
||||
print LOG "tinderbox: buildfamily: windows\n";
|
||||
print LOG "\n";
|
||||
close( LOG );
|
||||
system("$nstools\\bin\\blat logfile -t tinderbox-daemon\@warp" );
|
||||
}
|
||||
|
||||
sub parse_args {
|
||||
local($i);
|
||||
|
||||
if( @ARGV == 0 ){
|
||||
&usage;
|
||||
}
|
||||
$i = 0;
|
||||
while( $i < @ARGV ){
|
||||
if( $ARGV[$i] eq '--depend' ){
|
||||
$build_depend = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--clobber' ){
|
||||
$build_depend = 0;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--continue' ){
|
||||
$build_continue = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--noawt11' ){
|
||||
$noawt11 = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--no32' ){
|
||||
$no32 = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--no16' ){
|
||||
$no16 = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--test' ){
|
||||
$build_test = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-tag' ){
|
||||
$i++;
|
||||
$build_tag = $ARGV[$i];
|
||||
if( $build_tag eq '' || $build_tag eq '-t'){
|
||||
&usage;
|
||||
}
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-t' ){
|
||||
$i++;
|
||||
$build_tree = $ARGV[$i];
|
||||
if( $build_tree eq '' ){
|
||||
&usage;
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
if( $build_tree eq '' ){
|
||||
&usage;
|
||||
}
|
||||
}
|
||||
|
||||
sub usage {
|
||||
die "usage: buildit.pl [--depend | --clobber] [--no16] [--continue] [--test] [-tag TAGNAME] -t TREENAME\n";
|
||||
}
|
||||
|
||||
sub setup_env {
|
||||
local($p);
|
||||
$ENV{"MOZ_DEBUG"} = '1';
|
||||
$ENV{"MOZ_GOLD"} = '1';
|
||||
$ENV{"NO_SECURITY"} = '1';
|
||||
$ENV{"MOZ_MEDIUM"} = '1';
|
||||
$ENV{"MOZ_CAFE"} = '1';
|
||||
$ENV{"NSPR20"} = '1';
|
||||
$ENV{"VERBOSE"} = '1';
|
||||
$nstools = $ENV{"MOZ_TOOLS"};
|
||||
if( $nstools eq '' ){
|
||||
die "error: environment variable MOZ_TOOLS not set\n";
|
||||
}
|
||||
$msdev = $ENV{"MOZ_MSDEV"} = 'c:\msdev';
|
||||
if( $msdev eq '' ){
|
||||
die "error: environment variable MOZ_MSDEV not set\n";
|
||||
}
|
||||
$msvc = $ENV{"MOZ_MSVC"} = 'c:\msvc';
|
||||
if( $msvc eq '' ){
|
||||
die "error: environment variable MOZ_VC not set\n";
|
||||
}
|
||||
if ( $build_tag ne '' ) {
|
||||
$ENV{"MOZ_BRANCH"} = $build_tag;
|
||||
}
|
||||
$moz_src = $ENV{"MOZ_SRC"} = $start_dir;
|
||||
$ENV{"MOZ_DATE"} = $start_time_str;
|
||||
$src_16_drive = 'y:';
|
||||
}
|
||||
|
||||
sub print_env {
|
||||
local( $k, $v);
|
||||
print LOG "\nEnvironment\n";
|
||||
print "\nEnvironment\n";
|
||||
for $k (sort keys %ENV){
|
||||
$v = $ENV{$k};
|
||||
print LOG " $k=$v\n";
|
||||
print " $k=$v\n";
|
||||
}
|
||||
print LOG "\n";
|
||||
print "\n";
|
||||
system 'set';
|
||||
}
|
||||
|
||||
sub strip_config {
|
||||
$save_compname=$ENV{"COMPUTERNAME"};
|
||||
$save_userdomain=$ENV{"USERDOMAIN"};
|
||||
$save_username=$ENV{"USERNAME"};
|
||||
$save_userprofile=$ENV{"USERPROFILE"};
|
||||
# most of these deletes have no effect.
|
||||
delete($ENV{"COMPUTERNAME"});
|
||||
delete($ENV{"USERDOMAIN"});
|
||||
delete($ENV{"USERNAME"});
|
||||
delete($ENV{"USERPROFILE"});
|
||||
# delete($ENV{"WATCOM"});
|
||||
|
||||
}
|
||||
|
||||
sub restore_config {
|
||||
$ENV{"COMPUTERNAME"}=$save_compname;
|
||||
$ENV{"USERDOMAIN"}=$save_userdomain;
|
||||
$ENV{"USERNAME"}=$save_username;
|
||||
$ENV{"MSDevDir"}=$save_userprofile;
|
||||
&print_env;
|
||||
}
|
||||
31
mozilla/webtools/tinderbox/faq.html
Executable file
31
mozilla/webtools/tinderbox/faq.html
Executable file
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<META NAME="GENERATOR" CONTENT="Mozilla/4.0b2 (WinNT; I) [Netscape]">
|
||||
</HEAD>
|
||||
<BODY>
|
||||
|
||||
<H1>
|
||||
FAQ on Tinderbox </H1>
|
||||
<B><FONT SIZE=+2>Q. What is Tinderbox.</FONT></B>
|
||||
<BR><FONT SIZE=+2>A. Your very own automated build page. It shows you how builds
|
||||
are going on various platforms. fs</FONT>
|
||||
<BR><FONT SIZE=+2></FONT>
|
||||
<BR><B><FONT SIZE=+2>Q. I just checked in some code. How can I tell when
|
||||
I'm OK.</FONT></B>
|
||||
<BR><FONT SIZE=+2>A. You name will appear in the <I>guilty </I>column.
|
||||
When there are successful (<FONT COLOR="#00FF00">green</FONT>) builds in
|
||||
all the columns in a row <B>above</B> your name, you know you are ok.</FONT>
|
||||
<BR>
|
||||
<BR><B><FONT SIZE=+2>Q. The tree is broken, how do I find out what is busted
|
||||
(or who busted it).</FONT></B>
|
||||
<BR><FONT SIZE=+2>A. Clicking 'L' in the first red box (first build to break)
|
||||
above a green will show you a build log for the broken build. You
|
||||
can also click 'C' in this box and see what code was checked in.</FONT>
|
||||
<BR>
|
||||
<BR><B><FONT SIZE=+2>More Questions? Mail me <A HREF="mailto:ltabb@netscape.com">ltabb@netscape.com</A></FONT></B>
|
||||
<BR>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
217
mozilla/webtools/tinderbox/fixupimages.pl
Executable file
217
mozilla/webtools/tinderbox/fixupimages.pl
Executable file
@@ -0,0 +1,217 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use Socket;
|
||||
|
||||
require 'globals.pl';
|
||||
require 'imagelog.pl';
|
||||
|
||||
# Port an old-style imagelog thing to a newstyle one
|
||||
|
||||
open( IMAGELOG, "<$data_dir/imagelog.txt" ) || die "can't open file";
|
||||
open (OUT, ">$data_dir/newimagelog.txt") || die "can't open output file";
|
||||
select(OUT); $| = 1; select(STDOUT);
|
||||
|
||||
while( <IMAGELOG> ){
|
||||
chop;
|
||||
($url,$quote) = split(/\`/);
|
||||
print "$url\n";
|
||||
$size = &URLsize($url);
|
||||
$width = "";
|
||||
$height = "";
|
||||
if ($size =~ /WIDTH=([0-9]*)/) {
|
||||
$width = $1;
|
||||
}
|
||||
if ($size =~ /HEIGHT=([0-9]*)/) {
|
||||
$height = $1;
|
||||
}
|
||||
if ($width eq "" || $height eq "") {
|
||||
print "Couldn't get image size; skipping.\n";
|
||||
} else {
|
||||
print OUT "$url`$width`$height`$quote\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sub imgsize {
|
||||
local($file)= @_;
|
||||
|
||||
#first try to open the file
|
||||
if( !open(STREAM, "<$file") ){
|
||||
print "Can't open IMG $file";
|
||||
$size="";
|
||||
} else {
|
||||
if ($file =~ /.jpg/i || $file =~ /.jpeg/i) {
|
||||
$size = &jpegsize(STREAM);
|
||||
} elsif($file =~ /.gif/i) {
|
||||
$size = &gifsize(STREAM);
|
||||
} elsif($file =~ /.xbm/i) {
|
||||
$size = &xbmsize(STREAM);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
$_ = $size;
|
||||
if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
close(STREAM);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine gets the size of the specified GIF
|
||||
###########################################################################
|
||||
sub gifsize {
|
||||
local($GIF) = @_;
|
||||
read($GIF, $type, 6);
|
||||
if(!($type =~ /GIF8[7,9]a/) ||
|
||||
!(read($GIF, $s, 4) == 4) ){
|
||||
print "Invalid or Corrupted GIF";
|
||||
$size="";
|
||||
} else {
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join ("", 'WIDTH=', $b<<8|$a, ' HEIGHT=', $d<<8|$c);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
sub xbmsize {
|
||||
local($XBM) = @_;
|
||||
local($input)="";
|
||||
|
||||
$input .= <$XBM>;
|
||||
$input .= <$XBM>;
|
||||
$_ = $input;
|
||||
if( /#define\s*\S*\s*\d*\s*\n#define\s*\S*\s*\d*\s*\n/i ){
|
||||
($a,$b)=/#define\s*\S*\s*(\d*)\s*\n#define\s*\S*\s*(\d*)\s*\n/i;
|
||||
$size=join ("", 'WIDTH=', $a, ' HEIGHT=', $b );
|
||||
} else {
|
||||
print "Hmmm... Doesn't look like an XBM file";
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
# jpegsize : gets the width and height (in pixels) of a jpeg file
|
||||
# Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995
|
||||
# modified slightly by alex@ed.ac.uk
|
||||
sub jpegsize {
|
||||
local($JPEG) = @_;
|
||||
local($done)=0;
|
||||
$size="";
|
||||
|
||||
read($JPEG, $c1, 1); read($JPEG, $c2, 1);
|
||||
if( !((ord($c1) == 0xFF) && (ord($c2) == 0xD8))){
|
||||
printf "This is not a JPEG! (Codes %02X %02X)\n", ord($c1), ord($c2);
|
||||
$done=1;
|
||||
}
|
||||
while (ord($ch) != 0xDA && !$done) {
|
||||
# Find next marker (JPEG markers begin with 0xFF)
|
||||
# This can hang the program!!
|
||||
while (ord($ch) != 0xFF) { read($JPEG, $ch, 1); }
|
||||
# JPEG markers can be padded with unlimited 0xFF's
|
||||
while (ord($ch) == 0xFF) { read($JPEG, $ch, 1); }
|
||||
# Now, $ch contains the value of the marker.
|
||||
$marker=ord($ch);
|
||||
|
||||
if (($marker >= 0xC0) && ($marker <= 0xCF) &&
|
||||
($marker != 0xC4) && ($marker != 0xCC)) { # it's a SOFn marker
|
||||
read ($JPEG, $junk, 3); read($JPEG, $s, 4);
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join("", 'HEIGHT=',$a<<8|$b,' WIDTH=',$c<<8|$d );
|
||||
$done=1;
|
||||
} else {
|
||||
# We **MUST** skip variables, since FF's within variable
|
||||
# names are NOT valid JPEG markers
|
||||
read ($JPEG, $s, 2);
|
||||
($c1, $c2) = unpack("C"x2,$s);
|
||||
$length = $c1<<8|$c2;
|
||||
if( ($length < 2) ){
|
||||
print "Erroneous JPEG marker length";
|
||||
$done=1;
|
||||
} else {
|
||||
read($JPEG, $junk, $length-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine grabs a gif from another server and gets its size
|
||||
###########################################################################
|
||||
|
||||
|
||||
sub URLsize {
|
||||
my ($fullurl) = @_;
|
||||
my($dummy, $dummy, $serverstring, $url) = split(/\//, $fullurl, 4);
|
||||
my($them,$port) = split(/:/, $serverstring);
|
||||
my $port = 80 unless $port;
|
||||
$them = 'localhost' unless $them;
|
||||
my $size="";
|
||||
|
||||
$_=$url;
|
||||
if( /gif/i || /jpeg/i || /jpg/i || /xbm/i ) {
|
||||
my ($remote, $iaddr, $paddr, $proto, $line);
|
||||
$remote = $them;
|
||||
if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
|
||||
die "No port" unless $port;
|
||||
$iaddr = inet_aton($remote) || die "no host: $remote";
|
||||
$paddr = sockaddr_in($port, $iaddr);
|
||||
|
||||
$proto = getprotobyname('tcp');
|
||||
socket(S, PF_INET, SOCK_STREAM, $proto) || return "socket: $!";
|
||||
connect(S, $paddr) || return "connect: $!";
|
||||
select(S); $| = 1; select(STDOUT);
|
||||
|
||||
|
||||
|
||||
print S "GET /$url\n";
|
||||
if ($url =~ /.jpg/i || $url =~ /.jpeg/i) {
|
||||
$size = &jpegsize(S);
|
||||
} elsif($url =~ /.gif/i) {
|
||||
$size = &gifsize(S);
|
||||
} elsif($url =~ /.xbm/i) {
|
||||
$size = &xbmsize(S);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
$_ = $size;
|
||||
if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
} else {
|
||||
$size="";
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
sub dokill {
|
||||
kill 9,$child if $child;
|
||||
}
|
||||
556
mozilla/webtools/tinderbox/globals.pl
Executable file
556
mozilla/webtools/tinderbox/globals.pl
Executable file
@@ -0,0 +1,556 @@
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
#
|
||||
# Global variabls and functions for tinderbox
|
||||
#
|
||||
|
||||
#
|
||||
# Global variables
|
||||
#
|
||||
|
||||
$td1 = {};
|
||||
$td2 = {};
|
||||
|
||||
$build_list = []; # array of all build records
|
||||
$build_name_index = {};
|
||||
$ignore_builds = {};
|
||||
$build_name_names = [];
|
||||
$name_count = 0;
|
||||
|
||||
$build_time_index = {};
|
||||
$build_time_times = [];
|
||||
$time_count = 0;
|
||||
$mindate_time_count = 0; # time_count that corresponds to the mindate
|
||||
|
||||
$build_table = [];
|
||||
$who_list = [];
|
||||
$who_list2 = [];
|
||||
@note_array = ();
|
||||
|
||||
|
||||
#$body_tag = "<BODY TEXT=#000000 BGCOLOR=#8080C0 LINK=#FFFFFF VLINK=#800080 ALINK=#FFFF00>";
|
||||
#$body_tag = "<BODY TEXT=#000000 BGCOLOR=#FFFFC0 LINK=#0000FF VLINK=#800080 ALINK=#FF00FF>";
|
||||
if( $ENV{'USERNAME'} eq 'ltabb' ){
|
||||
$gzip = 'gzip';
|
||||
}
|
||||
else {
|
||||
$gzip = '/usr/local/bin/gzip';
|
||||
}
|
||||
|
||||
$data_dir='data';
|
||||
|
||||
$lock_count = 0;
|
||||
|
||||
1;
|
||||
|
||||
sub lock{
|
||||
#if( $lock_count == 0 ){
|
||||
# print "locking $tree/LOCKFILE.lck\n";
|
||||
# open( LOCKFILE_LOCK, ">$tree/LOCKFILE.lck" );
|
||||
# flock( LOCKFILE_LOCK, 2 );
|
||||
#}
|
||||
#$lock_count++;
|
||||
|
||||
}
|
||||
|
||||
sub unlock{
|
||||
#$lock_count--;
|
||||
#if( $lock_count == 0 ){
|
||||
# flock( LOCKFILE_LOCK, 8 );
|
||||
# close( LOCKFILE_LOCK );
|
||||
#}
|
||||
}
|
||||
|
||||
sub print_time {
|
||||
my ($t) = @_;
|
||||
my ($minute,$hour,$mday,$mon);
|
||||
(undef,$minute,$hour,$mday,$mon,undef) = localtime($t);
|
||||
sprintf("%02d/%02d %02d:%02d",$mon+1,$mday,$hour,$minute);
|
||||
}
|
||||
|
||||
sub url_encode {
|
||||
my ($s) = @_;
|
||||
|
||||
$s =~ s/\%/\%25/g;
|
||||
$s =~ s/\=/\%3d/g;
|
||||
$s =~ s/\?/\%3f/g;
|
||||
$s =~ s/ /\%20/g;
|
||||
$s =~ s/\n/\%0a/g;
|
||||
$s =~ s/\r//g;
|
||||
$s =~ s/\"/\%22/g;
|
||||
$s =~ s/\'/\%27/g;
|
||||
$s =~ s/\|/\%7c/g;
|
||||
$s =~ s/\&/\%26/g;
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub url_decode {
|
||||
my ($value) = @_;
|
||||
$value =~ tr/+/ /;
|
||||
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
sub value_encode {
|
||||
my ($s) = @_;
|
||||
$s =~ s@&@&@g;
|
||||
$s =~ s@<@<@g;
|
||||
$s =~ s@>@>@g;
|
||||
$s =~ s@\"@"@g;
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
sub load_data {
|
||||
$tree2 = $form{'tree2'};
|
||||
if( $tree2 ne '' ){
|
||||
require "$tree2/treedata.pl";
|
||||
if( -r "$tree2/ignorebuilds.pl" ){
|
||||
require "$tree2/ignorebuilds.pl";
|
||||
}
|
||||
|
||||
$td2 = {};
|
||||
$td2->{name} = $tree2;
|
||||
$td2->{cvs_module} = $cvs_module;
|
||||
$td2->{cvs_branch} = $cvs_branch;
|
||||
$td2->{num} = 1;
|
||||
$td2->{ignore_builds} = $ignore_builds;
|
||||
if( $cvs_root eq '' ){
|
||||
$cvs_root = '/m/src';
|
||||
}
|
||||
$td2->{cvs_root} = $cvs_root;
|
||||
|
||||
$tree = $form{'tree'};
|
||||
require "$tree/treedata.pl";
|
||||
if( $cvs_root eq '' ){
|
||||
$cvs_root = '/m/src';
|
||||
}
|
||||
}
|
||||
|
||||
$tree = $form{'tree'};
|
||||
|
||||
return unless $tree;
|
||||
#die "the 'tree' parameter must be provided\n" unless $tree;
|
||||
|
||||
if ( -r "$tree/treedata.pl" ) {
|
||||
require "$tree/treedata.pl";
|
||||
}
|
||||
|
||||
$ignore_builds = {};
|
||||
if( -r "$tree/ignorebuilds.pl" ){
|
||||
require "$tree/ignorebuilds.pl";
|
||||
}
|
||||
|
||||
$td1 = {};
|
||||
$td1->{name} = $tree;
|
||||
$td1->{num} = 0;
|
||||
$td1->{cvs_module} = $cvs_module;
|
||||
$td1->{cvs_branch} = $cvs_branch;
|
||||
$td1->{ignore_builds} = $ignore_builds;
|
||||
if( $cvs_root eq '' ){
|
||||
$cvs_root = '/m/src';
|
||||
}
|
||||
$td1->{cvs_root} = $cvs_root;
|
||||
|
||||
&lock;
|
||||
&load_buildlog;
|
||||
&unlock;
|
||||
|
||||
&get_build_name_index;
|
||||
&get_build_time_index;
|
||||
|
||||
&load_who($who_list, $td1);
|
||||
if( $tree2 ne '' ){
|
||||
&load_who($who_list2, $td2);
|
||||
}
|
||||
|
||||
&make_build_table;
|
||||
}
|
||||
|
||||
sub load_buildlog {
|
||||
my $mailtime, $buildtime, $buildname, $errorparser;
|
||||
my $buildstatus, $logfile,$binaryname;
|
||||
my $buildrec, @treelist, $t;
|
||||
|
||||
if (not defined $maxdate) {
|
||||
$maxdate = time();
|
||||
}
|
||||
if (not defined $mindate) {
|
||||
$mindate = $maxdate - 24*60*60;
|
||||
}
|
||||
|
||||
if ($tree2 ne '') {
|
||||
@treelist = ($td1, $td2);
|
||||
}
|
||||
else {
|
||||
@treelist = ($td1);
|
||||
}
|
||||
|
||||
for $t (@treelist) {
|
||||
use Backwards;
|
||||
my ($bw) = Backwards->new("$t->{name}/build.dat") or die;
|
||||
|
||||
my $tooearly = 0;
|
||||
while( $_ = $bw->readline ) {
|
||||
chomp;
|
||||
($mailtime, $buildtime, $buildname,
|
||||
$errorparser, $buildstatus, $logfile, $binaryname) = split /\|/;
|
||||
|
||||
# Ignore stuff in the future.
|
||||
next if $buildtime > $maxdate;
|
||||
|
||||
# Ignore stuff in the past (but get a 2 hours of extra data)
|
||||
if ($buildtime < $mindate - 2*60*60) {
|
||||
# Occasionally, a build might show up with a bogus time. So,
|
||||
# we won't judge ourselves as having hit the end until we
|
||||
# hit a full 20 lines in a row that are too early.
|
||||
last if $tooearly++ > 20;
|
||||
|
||||
next;
|
||||
}
|
||||
$tooearly = 0;
|
||||
$buildrec = {
|
||||
mailtime => $mailtime,
|
||||
buildtime => $buildtime,
|
||||
buildname => ($tree2 ne '' ? $t->{name} . ' ' : '' ) . $buildname,
|
||||
errorparser => $errorparser,
|
||||
buildstatus => $buildstatus,
|
||||
logfile => $logfile,
|
||||
binaryname => $binaryname,
|
||||
td => $t
|
||||
};
|
||||
if ($form{noignore} or not $t->{ignore_builds}->{$buildname}) {
|
||||
push @{$build_list}, $buildrec;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub loadquickparseinfo {
|
||||
my ($tree, $build, $times) = (@_);
|
||||
|
||||
do "$tree/ignorebuilds.pl";
|
||||
|
||||
use Backwards;
|
||||
|
||||
my ($bw) = Backwards->new("$form{tree}/build.dat") or die;
|
||||
|
||||
my $latest_time = 0;
|
||||
my $tooearly = 0;
|
||||
while( $_ = $bw->readline ) {
|
||||
chop;
|
||||
my ($buildtime, $buildname, $buildstatus) = (split /\|/)[1,2,4];
|
||||
|
||||
if ($buildstatus =~ /^success|busted|testfailed$/) {
|
||||
|
||||
# Ignore stuff in the future.
|
||||
next if $buildtime > $maxdate;
|
||||
|
||||
$latest_time = $buildtime if $buildtime > $latest_time;
|
||||
|
||||
# Ignore stuff more than 12 hours old
|
||||
if ($buildtime < $latest_time - 12*60*60) {
|
||||
# Hack: A build may give a bogus time. To compensate, we will
|
||||
# not stop until we hit 20 consecutive lines that are too early.
|
||||
|
||||
last if $tooearly++ > 20;
|
||||
next;
|
||||
}
|
||||
$tooearly = 0;
|
||||
|
||||
next if exists $ignore_builds->{$buildname};
|
||||
next if exists $build->{$buildname}
|
||||
and $times->{$buildname} >= $buildtime;
|
||||
|
||||
$build->{$buildname} = $buildstatus;
|
||||
$times->{$buildname} = $buildtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub load_who {
|
||||
my ($who_list, $td) = @_;
|
||||
my $d, $w, $i, $bfound;
|
||||
|
||||
open(WHOLOG, "<$td->{name}/who.dat");
|
||||
while (<WHOLOG>) {
|
||||
$i = $time_count;
|
||||
chop;
|
||||
($d,$w) = split /\|/;
|
||||
$bfound = 0;
|
||||
while ($i > 0 and not $bfound) {
|
||||
if ($d <= $build_time_times->[$i]) {
|
||||
$who_list->[$i+1]->{$w} = 1;
|
||||
$bfound = 1;
|
||||
}
|
||||
else {
|
||||
$i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Ignore the last one
|
||||
#
|
||||
if ($time_count > 0) {
|
||||
$who_list->[$time_count] = {};
|
||||
}
|
||||
}
|
||||
|
||||
sub get_build_name_index {
|
||||
my $i,$br;
|
||||
|
||||
# Get all the unique build names.
|
||||
#
|
||||
foreach $br (@{$build_list}) {
|
||||
$build_name_index->{$br->{buildname}} = 1;
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
foreach $n (sort keys (%{$build_name_index})) {
|
||||
$build_name_names->[$i] = $n;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$name_count = @{$build_name_names}-1;
|
||||
|
||||
# Update the map so it points to the right index
|
||||
#
|
||||
for ($i=1; $i < $name_count+1; $i++) {
|
||||
$build_name_index->{$build_name_names->[$i]} = $i;
|
||||
}
|
||||
}
|
||||
|
||||
sub get_build_time_index {
|
||||
my $i,$br;
|
||||
|
||||
# Get all the unique build names.
|
||||
#
|
||||
foreach $br (@{$build_list}) {
|
||||
$build_time_index->{$br->{buildtime}} = 1;
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
foreach $n (sort {$b <=> $a} keys (%{$build_time_index})) {
|
||||
$build_time_times->[$i] = $n;
|
||||
$mindate_time_count = $i if $n >= $mindate;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$time_count = @{$build_time_times}-1;
|
||||
|
||||
# Update the map so it points to the right index
|
||||
#
|
||||
for ($i=1; $i < $time_count+1; $i++) {
|
||||
$build_time_index->{$build_time_times->[$i]} = $i;
|
||||
}
|
||||
|
||||
#for $i (@{$build_time_times}) {
|
||||
# print $i . "\n";
|
||||
#}
|
||||
|
||||
#while( ($k,$v) = each(%{$build_time_index})) {
|
||||
# print "$k=$v\n";
|
||||
#}
|
||||
}
|
||||
|
||||
sub make_build_table {
|
||||
my $i,$ti,$bi,$ti1,$br;
|
||||
|
||||
# Create the build table
|
||||
#
|
||||
for ($i=1; $i <= $time_count; $i++){
|
||||
$build_table->[$i] = [];
|
||||
}
|
||||
|
||||
# Populate the build table with build data
|
||||
#
|
||||
foreach $br (reverse @{$build_list}) {
|
||||
$ti = $build_time_index->{$br->{buildtime}};
|
||||
$bi = $build_name_index->{$br->{buildname}};
|
||||
$build_table->[$ti][$bi] = $br;
|
||||
}
|
||||
|
||||
&load_notes;
|
||||
|
||||
for ($bi = $name_count; $bi > 0; $bi--) {
|
||||
for ($ti = $time_count; $ti > 0; $ti--) {
|
||||
if (defined($br = $build_table->[$ti][$bi])
|
||||
and not defined($br->{rowspan})) {
|
||||
|
||||
# If the cell immediately after us is defined, then we
|
||||
# can have a previousbuildtime.
|
||||
if (defined($br1 = $build_table->[$ti+1][$bi])) {
|
||||
$br->{previousbuildtime} = $br1->{buildtime};
|
||||
}
|
||||
|
||||
$ti1 = $ti-1;
|
||||
while ($ti1 > 0 and not defined($build_table->[$ti1][$bi])) {
|
||||
$build_table->[$ti1][$bi] = -1;
|
||||
$ti1--;
|
||||
}
|
||||
$br->{rowspan} = $ti - $ti1;
|
||||
if ($br->{rowspan} != 1) {
|
||||
$build_table->[$ti1+1][$bi] = $br;
|
||||
$build_table->[$ti][$bi] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub load_notes {
|
||||
if ($tree2 ne '') {
|
||||
@treelist = ($td1, $td2);
|
||||
}
|
||||
else {
|
||||
@treelist = ($td1);
|
||||
}
|
||||
|
||||
foreach $t (@treelist) {
|
||||
open(NOTES,"<$t->{name}/notes.txt")
|
||||
or print "<h2>warning: Couldn't open $t->{name}/notes.txt </h2>\n";
|
||||
while (<NOTES>) {
|
||||
chop;
|
||||
($nbuildtime,$nbuildname,$nwho,$nnow,$nenc_note) = split /\|/;
|
||||
$nbuildname = "$t->{name} $nbuildname" if $tree2 ne '';
|
||||
$ti = $build_time_index->{$nbuildtime};
|
||||
$bi = $build_name_index->{$nbuildname};
|
||||
#print "[ti = $ti][bi=$bi][buildname='$nbuildname' $_<br>";
|
||||
if ($ti != 0 and $bi != 0) {
|
||||
$build_table->[$ti][$bi]->{hasnote} = 1;
|
||||
if (not defined($build_table->[$ti][$bi]->{noteid})) {
|
||||
$build_table->[$ti][$bi]->{noteid} = (0+@note_array);
|
||||
}
|
||||
$noteid = $build_table->[$ti][$bi]->{noteid};
|
||||
$now_str = &print_time($nnow);
|
||||
$note = &url_decode($nenc_note);
|
||||
$note_array[$noteid] = "<pre>\n[<b><a href=mailto:$nwho>"
|
||||
."$nwho</a> - $now_str</b>]\n$note\n</pre>"
|
||||
.$note_array[$noteid];
|
||||
}
|
||||
}
|
||||
close(NOTES);
|
||||
}
|
||||
}
|
||||
|
||||
sub last_success_time {
|
||||
my ($row) = @_;
|
||||
|
||||
for (my $tt=1; $tt <= $time_count; $tt++) {
|
||||
my $br = $build_table->[$tt][$row];
|
||||
next unless defined $br;
|
||||
next unless $br->{buildstatus} eq 'success';
|
||||
return $build_time_times->[$tt + $br->{rowspan} ];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub last_status {
|
||||
my ($row) = @_;
|
||||
|
||||
for (my $tt=1; $tt <= $time_count; $tt++) {
|
||||
my $br = $build_table->[$tt][$row];
|
||||
next unless defined $br;
|
||||
next unless $br->{buildstatus} =~ /^(success|busted|testfailed)$/;
|
||||
return $br->{buildstatus};
|
||||
}
|
||||
return 'building';
|
||||
}
|
||||
|
||||
sub check_password {
|
||||
if ($form{password} eq '') {
|
||||
if (defined $cookie_jar{tinderbox_password}) {
|
||||
$form{password} = $cookie_jar{tinderbox_password};
|
||||
}
|
||||
}
|
||||
my $correct = '';
|
||||
if (open(REAL, '<data/passwd')) {
|
||||
$correct = <REAL>;
|
||||
close REAL;
|
||||
$correct =~ s/\s+$//; # Strip trailing whitespace.
|
||||
}
|
||||
$form{password} =~ s/\s+$//; # Strip trailing whitespace.
|
||||
if ($form{password} ne '') {
|
||||
open(TRAPDOOR, "../bonsai/data/trapdoor $form{'password'} |")
|
||||
or die "Can't run trapdoor func!";
|
||||
my $encoded = <TRAPDOOR>;
|
||||
close TRAPDOOR;
|
||||
$encoded =~ s/\s+$//; # Strip trailing whitespace.
|
||||
if ($encoded eq $correct) {
|
||||
if ($form{rememberpassword} ne '') {
|
||||
print "Set-Cookie: tinderbox_password=$form{'password'} ;"
|
||||
." path=/ ; expires = Sun, 1-Mar-2020 00:00:00 GMT\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
require 'header.pl';
|
||||
|
||||
print "Content-type: text/html\n";
|
||||
print "Set-Cookie: tinderbox_password= ; path=/ ; "
|
||||
." expires = Sun, 1-Mar-2020 00:00:00 GMT\n";
|
||||
print "\n";
|
||||
|
||||
EmitHtmlHeader("What's the magic word?",
|
||||
"You need to know the magic word to use this page.");
|
||||
|
||||
if ($form{password} ne '') {
|
||||
print "<B>Invalid password; try again.<BR></B>";
|
||||
}
|
||||
print q(
|
||||
<FORM method=post>
|
||||
<B>Password:</B>
|
||||
<INPUT NAME=password TYPE=password><BR>
|
||||
<INPUT NAME=rememberpassword TYPE=checkbox>
|
||||
If correct, remember password as a cookie<BR>
|
||||
);
|
||||
|
||||
while (my ($key,$value) = each %form) {
|
||||
next if $key eq "password" or $key eq "rememberpassword";
|
||||
|
||||
my $enc = value_encode($value);
|
||||
print "<INPUT TYPE=HIDDEN NAME=$key VALUE='$enc'>\n";
|
||||
}
|
||||
print "<INPUT TYPE=SUBMIT value=Submit></FORM>\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
sub find_build_record {
|
||||
my ($tree, $logfile) = @_;
|
||||
|
||||
my $log_entry = `grep $logfile $tree/build.dat`;
|
||||
|
||||
chomp($log_entry);
|
||||
my ($mailtime, $buildtime, $buildname, $errorparser,
|
||||
$buildstatus, $logfile, $binaryname) = split /\|/, $log_entry;
|
||||
|
||||
$buildrec = {
|
||||
mailtime => $mailtime,
|
||||
buildtime => $buildtime,
|
||||
buildname => $buildname,
|
||||
errorparser => $errorparser,
|
||||
buildstatus => $buildstatus,
|
||||
logfile => $logfile,
|
||||
binaryname => $binaryname,
|
||||
td => undef
|
||||
};
|
||||
return $buildrec;
|
||||
}
|
||||
49
mozilla/webtools/tinderbox/handlemail.pl
Executable file
49
mozilla/webtools/tinderbox/handlemail.pl
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
# Figure out which directory tinderbox is in by looking at argv[0]. Unless
|
||||
# there is a command line argument; if there is, just use that.
|
||||
|
||||
$tinderboxdir = $0;
|
||||
$tinderboxdir =~ s:/[^/]*$::; # Remove last word, and slash before it.
|
||||
if ($tinderboxdir eq "") {
|
||||
$tinderboxdir = ".";
|
||||
}
|
||||
|
||||
if (@ARGV > 0) {
|
||||
$tinderboxdir = $ARGV[0];
|
||||
}
|
||||
|
||||
print "tinderbox = $tinderboxdir\n";
|
||||
|
||||
chdir $tinderboxdir || die "Couldn't chdir to $tinderboxdir";
|
||||
|
||||
|
||||
open(DF, ">data/tbx.$$") || die "could not open data/tbx.$$";
|
||||
while(<STDIN>){
|
||||
print DF $_;
|
||||
}
|
||||
close(DF);
|
||||
|
||||
$err = system("./processbuild.pl data/tbx.$$");
|
||||
|
||||
if( $err ) {
|
||||
die "processbuild.pl returned an error\n";
|
||||
}
|
||||
|
||||
43
mozilla/webtools/tinderbox/imagelog.pl
Executable file
43
mozilla/webtools/tinderbox/imagelog.pl
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
1;
|
||||
|
||||
sub add_imagelog {
|
||||
local($url,$quote,$width,$height) = @_;
|
||||
open( IMAGELOG, ">>$data_dir/imagelog.txt" ) || die "Oops; can't open imagelog.txt";
|
||||
print IMAGELOG "$url`$width`$height`$quote\n";
|
||||
close( IMAGELOG );
|
||||
}
|
||||
|
||||
sub get_image{
|
||||
local(@log,@ret,$i);
|
||||
|
||||
open( IMAGELOG, "<$data_dir/imagelog.txt" );
|
||||
@log = <IMAGELOG>;
|
||||
|
||||
# return a random line
|
||||
srand;
|
||||
@ret = split(/\`/,$log[rand @log]);
|
||||
|
||||
close( IMAGELOG );
|
||||
@ret;
|
||||
}
|
||||
|
||||
|
||||
12
mozilla/webtools/tinderbox/index.html
Executable file
12
mozilla/webtools/tinderbox/index.html
Executable file
@@ -0,0 +1,12 @@
|
||||
<TITLE>tinderbox</TITLE>
|
||||
<META HTTP-EQUIV="Refresh" CONTENT="1; URL=showbuilds.cgi">
|
||||
<BODY BGCOLOR="#FFFFFF" TEXT="#000000"
|
||||
LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
|
||||
<CENTER>
|
||||
<TABLE BORDER=0 WIDTH="100%" HEIGHT="100%"><TR><TD ALIGN=CENTER VALIGN=CENTER>
|
||||
<FONT SIZE="+2">
|
||||
You're looking for
|
||||
<A HREF="showbuilds.cgi">showbuilds.cgi</A>.
|
||||
</FONT>
|
||||
</TD></TR></TABLE>
|
||||
</CENTER>
|
||||
241
mozilla/webtools/tinderbox/processbuild.pl
Executable file
241
mozilla/webtools/tinderbox/processbuild.pl
Executable file
@@ -0,0 +1,241 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
require 'globals.pl';
|
||||
require 'timelocal.pl';
|
||||
|
||||
umask 0;
|
||||
|
||||
#$logfile = '';
|
||||
|
||||
%MAIL_HEADER = ();
|
||||
$DONE = 0;
|
||||
$building = 0;
|
||||
$endsection = 0;
|
||||
|
||||
open( LOG, "<$ARGV[0]") || die "cant open $!";
|
||||
&parse_mail_header;
|
||||
while ($DONE == 0) {
|
||||
%tbx = ();
|
||||
&get_variables;
|
||||
|
||||
# run thru if EOF and we haven't hit our section end marker
|
||||
|
||||
if ( !$DONE || !$endsection) {
|
||||
&check_required_vars;
|
||||
$tree = $tbx{'tree'} if (!defined($tree));
|
||||
$logfile = "$builddate.$$.gz" if (!defined($logfile));
|
||||
$building++ if ($tbx{'status'} =~ m/building/);
|
||||
&lock;
|
||||
&write_build_data;
|
||||
&unlock;
|
||||
}
|
||||
}
|
||||
close(LOG);
|
||||
|
||||
&compress_log_file;
|
||||
&unlink_log_file;
|
||||
|
||||
system "./buildwho.pl $tree";
|
||||
|
||||
# Build static pages for Sidebar flash and tinderbox panels.
|
||||
$ENV{QUERY_STRING}="tree=$tree&static=1";
|
||||
system './showbuilds.cgi';
|
||||
|
||||
# end of main
|
||||
######################################################################
|
||||
|
||||
|
||||
# This routine will scan through log looking for 'tinderbox:' variables
|
||||
#
|
||||
sub get_variables{
|
||||
|
||||
#while( ($k,$v) = each( %MAIL_HEADER ) ){
|
||||
# print "$k='$v'\n";
|
||||
#}
|
||||
|
||||
&parse_log_variables;
|
||||
|
||||
#while( ($k,$v) = each( %tbx ) ){
|
||||
# print "$k='$v'\n";
|
||||
#}
|
||||
}
|
||||
|
||||
|
||||
sub parse_log_variables {
|
||||
my ($line, $stop);
|
||||
$stop = 0;
|
||||
while($stop == 0){
|
||||
$line = <LOG>;
|
||||
$DONE++, return if !defined($line);
|
||||
chomp($line);
|
||||
if( $line =~ /^tinderbox\:/ ){
|
||||
if( $line =~ /^tinderbox\:[ \t]*([^:]*)\:[ \t]*([^\n]*)/ ){
|
||||
$tbx{$1} = $2;
|
||||
} elsif ( $line =~ /^tinderbox: END/ ) {
|
||||
$stop++, $endsection++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_mail_header {
|
||||
my $line;
|
||||
my $name = '';
|
||||
while($line = <LOG> ){
|
||||
chomp($line);
|
||||
|
||||
if( $line eq '' ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( $line =~ /([^ :]*)\:[ \t]+([^\n]*)/ ){
|
||||
$name = $1;
|
||||
$name =~ tr/A-Z/a-z/;
|
||||
$MAIL_HEADER{$name} = $2;
|
||||
#print "$name $2\n";
|
||||
}
|
||||
elsif( $name ne '' ){
|
||||
$MAIL_HEADER{$name} .= $2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub check_required_vars {
|
||||
$err_string = '';
|
||||
if( $tbx{'tree'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:tree' not set.\n";
|
||||
}
|
||||
elsif( ! -r $tbx{'tree'} ){
|
||||
$err_string .= "Variable 'tinderbox:tree' not set to a valid tree.\n";
|
||||
}
|
||||
elsif(($MAIL_HEADER{'to'} =~ /external/i ||
|
||||
$MAIL_HEADER{'cc'} =~ /external/i) &&
|
||||
$tbx{'tree'} !~ /external/i) {
|
||||
$err_string .= "Data from an external source didn't specify an 'external' tree.";
|
||||
}
|
||||
if( $tbx{'build'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:build' not set.\n";
|
||||
}
|
||||
if( $tbx{'errorparser'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:errorparser' not set.\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Grab the date in the form of mm/dd/yy hh:mm:ss
|
||||
#
|
||||
# Or a GMT unix date
|
||||
#
|
||||
if( $tbx{'builddate'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:builddate' not set.\n";
|
||||
}
|
||||
else {
|
||||
if( $tbx{'builddate'} =~
|
||||
/([0-9]*)\/([0-9]*)\/([0-9]*)[ \t]*([0-9]*)\:([0-9]*)\:([0-9]*)/ ){
|
||||
|
||||
$builddate = timelocal($6,$5,$4,$2,$1-1,$3);
|
||||
|
||||
}
|
||||
elsif( $tbx{'builddate'} > 7000000 ){
|
||||
$builddate = $tbx{'builddate'};
|
||||
}
|
||||
else {
|
||||
$err_string .= "Variable 'tinderbox:builddate' not of the form MM/DD/YY HH:MM:SS or unix date\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# Build Status
|
||||
#
|
||||
if( $tbx{'status'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:status' not set.\n";
|
||||
}
|
||||
elsif( ! $tbx{'status'} =~ /success|busted|building|testfailed/ ){
|
||||
$err_string .= "Variable 'tinderbox:status' must be 'success', 'busted', 'testfailed', or 'building'\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Report errors
|
||||
#
|
||||
if( $err_string ne '' ){
|
||||
die $err_string;
|
||||
}
|
||||
}
|
||||
|
||||
sub write_build_data {
|
||||
$t = time;
|
||||
open( BUILDDATA, ">>$tbx{'tree'}/build.dat" )|| die "can't open $! for writing";
|
||||
print BUILDDATA "$t|$builddate|$tbx{'build'}|$tbx{'errorparser'}|$tbx{'status'}|$logfile|$tbx{binaryname}\n";
|
||||
close( BUILDDATA );
|
||||
}
|
||||
|
||||
sub compress_log_file {
|
||||
local( $done, $line);
|
||||
|
||||
return if ( $building );
|
||||
|
||||
open( LOG2, "<$ARGV[0]") || die "cant open $!";
|
||||
|
||||
#
|
||||
# Skip past the the RFC822.HEADER
|
||||
#
|
||||
$done = 0;
|
||||
while( !$done && ($line = <LOG2>) ){
|
||||
chomp($line);
|
||||
$done = ($line eq '');
|
||||
}
|
||||
|
||||
open( ZIPLOG, "| $gzip -c > ${tree}/$logfile" ) || die "can't open $! for writing";
|
||||
$inBinary = 0;
|
||||
$hasBinary = ($tbx{'binaryname'} ne '');
|
||||
while( $line = <LOG2> ){
|
||||
if( !$inBinary ){
|
||||
print ZIPLOG $line;
|
||||
if( $hasBinary ){
|
||||
$inBinary = ($line =~ /^begin [0-7][0-7][0-7] /);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( $line =~ /^end\n/ ){
|
||||
$inBinary = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
close( ZIPLOG );
|
||||
close( LOG2 );
|
||||
|
||||
#
|
||||
# If a uuencoded binary is part of the build, unpack it.
|
||||
#
|
||||
if( $hasBinary ){
|
||||
$bin_dir = "$tbx{'tree'}/bin/$builddate/$tbx{'build'}";
|
||||
$bin_dir =~ s/ //g;
|
||||
|
||||
system("mkdir -m 0777 -p $bin_dir");
|
||||
|
||||
# LTNOTE: I'm not sure this is cross platform.
|
||||
system("/tools/ns/bin/uudecode --output-file=$bin_dir/$tbx{binaryname} < $ARGV[0]");
|
||||
}
|
||||
}
|
||||
|
||||
sub unlink_log_file {
|
||||
unlink( $ARGV[0] );
|
||||
}
|
||||
BIN
mozilla/webtools/tinderbox/reledanim.gif
Normal file
BIN
mozilla/webtools/tinderbox/reledanim.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
782
mozilla/webtools/tinderbox/showbuilds.cgi
Executable file
782
mozilla/webtools/tinderbox/showbuilds.cgi
Executable file
@@ -0,0 +1,782 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib '../bonsai';
|
||||
require 'globals.pl';
|
||||
require 'lloydcgi.pl';
|
||||
require 'imagelog.pl';
|
||||
require 'header.pl';
|
||||
$|=1;
|
||||
|
||||
# Hack this until I can figure out how to do get default root. -slamm
|
||||
$default_root = '/cvsroot';
|
||||
|
||||
# Show 12 hours by default
|
||||
#
|
||||
$nowdate = time;
|
||||
if (not defined($maxdate = $form{maxdate})) {
|
||||
$maxdate = $nowdate;
|
||||
}
|
||||
if ($form{showall}) {
|
||||
$mindate = 0;
|
||||
}
|
||||
else {
|
||||
$default_hours = 12;
|
||||
$hours = $default_hours;
|
||||
$hours = $form{hours} if $form{hours};
|
||||
$mindate = $maxdate - ($hours*60*60);
|
||||
}
|
||||
|
||||
%colormap = (
|
||||
success => '00ff00',
|
||||
busted => 'red',
|
||||
building => 'yellow',
|
||||
testfailed => 'orange'
|
||||
);
|
||||
|
||||
%images = (
|
||||
flames => '1afi003r.gif',
|
||||
star => 'star.gif'
|
||||
);
|
||||
|
||||
$tree = $form{tree};
|
||||
|
||||
if (exists $form{rebuildguilty} or exists $form{showall}) {
|
||||
system ("./buildwho.pl -days 7 $tree > /dev/null");
|
||||
undef $form{rebuildguilty};
|
||||
}
|
||||
&show_tree_selector, exit if $form{tree} eq '';
|
||||
&do_quickparse, exit if $form{quickparse};
|
||||
&do_express, exit if $form{express};
|
||||
&do_rdf, exit if $form{rdf};
|
||||
&do_static, exit if $form{static};
|
||||
&do_flash, exit if $form{flash};
|
||||
&do_panel, exit if $form{panel};
|
||||
&do_tinderbox, exit;
|
||||
|
||||
# end of main
|
||||
#=====================================================================
|
||||
|
||||
sub make_tree_list {
|
||||
my @result;
|
||||
while(<*>) {
|
||||
if( -d $_ && $_ ne 'data' && $_ ne 'CVS' && -f "$_/treedata.pl") {
|
||||
push @result, $_;
|
||||
}
|
||||
}
|
||||
return @result;
|
||||
}
|
||||
|
||||
sub show_tree_selector {
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
EmitHtmlHeader("tinderbox");
|
||||
|
||||
print "<P><TABLE WIDTH=\"100%\">";
|
||||
print "<TR><TD ALIGN=CENTER>Select one of the following trees:</TD></TR>";
|
||||
print "<TR><TD ALIGN=CENTER>\n";
|
||||
print " <TABLE><TR><TD><UL>\n";
|
||||
|
||||
my @list = make_tree_list();
|
||||
|
||||
foreach (@list) {
|
||||
print "<LI><a href=showbuilds.cgi?tree=$_>$_</a>\n";
|
||||
}
|
||||
print "<//UL></TD></TR></TABLE></TD></TR></TABLE>";
|
||||
|
||||
print "<P><TABLE WIDTH=\"100%\">";
|
||||
print "<TR><TD ALIGN=CENTER><a href=admintree.cgi>";
|
||||
print "Administer</a> one of the following trees:</TD></TR>";
|
||||
print "<TR><TD ALIGN=CENTER>\n";
|
||||
print " <TABLE><TR><TD><UL>\n";
|
||||
|
||||
foreach (@list) {
|
||||
print "<LI><a href=admintree.cgi?tree=$_>$_</a>\n";
|
||||
}
|
||||
print "<//UL></TD></TR></TABLE></TD></TR></TABLE>";
|
||||
}
|
||||
|
||||
sub do_static {
|
||||
local *OUT;
|
||||
|
||||
$form{nocrap}=1;
|
||||
|
||||
my @pages = ( ['index.html', 'do_tinderbox'],
|
||||
['flash.rdf', 'do_flash'],
|
||||
['panel.html', 'do_panel'] );
|
||||
|
||||
$rel_path = '../';
|
||||
while (($key, $value) = each %images) {
|
||||
$images{$key} = "$rel_path$value";
|
||||
}
|
||||
|
||||
my $oldfh = select;
|
||||
|
||||
foreach $pair (@pages) {
|
||||
my ($page, $call) = @{$pair};
|
||||
my $outfile = "$form{tree}/$page";
|
||||
|
||||
open(OUT,">$outfile.$$");
|
||||
select OUT;
|
||||
|
||||
eval "$call";
|
||||
|
||||
close(OUT);
|
||||
system "mv $outfile.$$ $outfile";
|
||||
}
|
||||
select $oldfh;
|
||||
}
|
||||
|
||||
sub do_tinderbox {
|
||||
&load_data;
|
||||
&print_page_head;
|
||||
&print_table_header;
|
||||
&print_table_body;
|
||||
&print_table_footer;
|
||||
}
|
||||
|
||||
sub print_page_head {
|
||||
|
||||
print "Content-type: text/html",
|
||||
($nowdate eq $maxdate ? "\nRefresh: 900" : ''),
|
||||
"\n\n<HTML>\n" unless $form{static};
|
||||
|
||||
# Get the message of the day only on the first pageful
|
||||
do "$tree/mod.pl" if $nowdate eq $maxdate;
|
||||
|
||||
use POSIX qw(strftime);
|
||||
# Print time in format, "HH:MM timezone"
|
||||
my $now = strftime("%H:%M %Z", localtime);
|
||||
|
||||
EmitHtmlTitleAndHeader("tinderbox: $tree", "tinderbox",
|
||||
"tree: $tree ($now)");
|
||||
|
||||
&print_javascript;
|
||||
|
||||
print "$message_of_day\n";
|
||||
|
||||
# Quote and Lengend
|
||||
#
|
||||
unless ($form{nocrap}) {
|
||||
my ($imageurl,$imagewidth,$imageheight,$quote) = &get_image;
|
||||
print qq{
|
||||
<table width="100%" cellpadding=0 cellspacing=0>
|
||||
<tr>
|
||||
<td valign=bottom>
|
||||
<p><center><a href=addimage.cgi><img src="$rel_path$imageurl"
|
||||
width=$imagewidth height=$imageheight><br>
|
||||
$quote</a><br>
|
||||
</center>
|
||||
<p>
|
||||
<td align=right valign=bottom>
|
||||
<table cellspacing=0 cellpadding=1 border=0><tr><td align=center>
|
||||
<TT>L</TT></td><td>= Show Build Log
|
||||
</td></tr><tr><td align=center>
|
||||
<img src="$images{star}"></td><td>= Show Log comments
|
||||
</td></tr><tr><td colspan=2>
|
||||
<table cellspacing=1 cellpadding=1 border=1>
|
||||
<tr bgcolor="$colormap{success}"><td>Successful Build
|
||||
<tr bgcolor="$colormap{building}"><td>Build in Progress
|
||||
<tr bgcolor="$colormap{testfailed}"><td>Successful Build,
|
||||
but Tests Failed
|
||||
<tr bgcolor="$colormap{busted}"><td>Build Failed
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
};
|
||||
}
|
||||
if ($bonsai_tree) {
|
||||
print "The tree is currently <font size=+2>";
|
||||
print (&tree_open ? 'OPEN' : 'CLOSED');
|
||||
print "</font>\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub print_table_body {
|
||||
for (my $tt=1; $tt <= $time_count; $tt++) {
|
||||
last if $build_time_times->[$tt] < $mindate;
|
||||
print_table_row($tt);
|
||||
}
|
||||
}
|
||||
|
||||
sub print_table_row {
|
||||
my ($tt) = @_;
|
||||
|
||||
# Time column
|
||||
#
|
||||
my $query_link = '';
|
||||
my $end_query = '';
|
||||
my $pretty_time = &print_time($build_time_times->[$tt]);
|
||||
|
||||
($hour) = $pretty_time =~ /(\d\d):/;
|
||||
|
||||
if ($lasthour != $hour or &has_who_list($tt)) {
|
||||
$query_link = &query_ref($td1, $build_time_times->[$tt]);
|
||||
$end_query = '</a>';
|
||||
}
|
||||
if ($lasthour == $hour) {
|
||||
$pretty_time =~ s/^.* //;
|
||||
} else {
|
||||
$lasthour = $hour;
|
||||
}
|
||||
|
||||
my $hour_color = '';
|
||||
$hour_color = ' bgcolor=#e7e7e7' if $build_time_times->[$tt] % 7200 <= 3600;
|
||||
print "<tr align=center><td align=right$hour_color>",
|
||||
"$query_link\n$pretty_time$end_query</td>\n";
|
||||
|
||||
# Guilty
|
||||
#
|
||||
print '<td>';
|
||||
for $who (sort keys %{$who_list->[$tt]} ){
|
||||
$qr = &who_menu($td1, $build_time_times->[$tt],
|
||||
$build_time_times->[$tt-1],$who);
|
||||
$who =~ s/%.*$//;
|
||||
print " ${qr}$who</a>\n";
|
||||
}
|
||||
print '</td>';
|
||||
|
||||
# Build Status
|
||||
#
|
||||
for ($bn=1; $bn <= $name_count; $bn++) {
|
||||
if (not defined($br = $build_table->[$tt][$bn])) {
|
||||
# No build data for this time
|
||||
print "<td></td>\n";
|
||||
next;
|
||||
}
|
||||
next if $br == -1; # rowspan has covered this row
|
||||
|
||||
$hasnote = $br->{hasnote};
|
||||
$noteid = $hasnote ? $br->{noteid} : 0;
|
||||
$rowspan = $br->{rowspan};
|
||||
$rowspan = $mindate_time_count - $tt + 1
|
||||
if $tt + $rowspan - 1 > $mindate_time_count;
|
||||
$color = $colormap{$br->{buildstatus}};
|
||||
$status = $br->{buildstatus};
|
||||
print "<td rowspan=$rowspan bgcolor=${color}>\n";
|
||||
|
||||
$logfile = $br->{logfile};
|
||||
$errorparser = $br->{errorparser};
|
||||
$buildname = $br->{buildname};
|
||||
$buildtime = $br->{buildtime};
|
||||
$buildtree = $br->{td}->{name};
|
||||
|
||||
print "<tt>\n";
|
||||
|
||||
# Build Note
|
||||
#
|
||||
$buildname = &url_encode($buildname);
|
||||
my $logurl = "${rel_path}showlog.cgi?log=$buildtree/$logfile";
|
||||
|
||||
if ($hasnote) {
|
||||
print "<a href='$logurl' onclick=\"return ",
|
||||
"note(event,$noteid,'$logfile');\">",
|
||||
"<img src='$images{star}' border=0></a>\n";
|
||||
}
|
||||
|
||||
# Build Log
|
||||
#
|
||||
print "<A HREF='$logurl' onclick=\"return log(event,$bn,'$logfile');\">";
|
||||
print "L</a>";
|
||||
|
||||
# What Changed
|
||||
#
|
||||
if( $br->{previousbuildtime} ){
|
||||
my $previous_br = $build_table->[$tt+$rowspan][$bn];
|
||||
my $previous_rowspan = $previous_br->{rowspan};
|
||||
if (&has_who_list($tt+$rowspan,
|
||||
$tt+$rowspan+$previous_rowspan-1)) {
|
||||
print "\n", &query_ref($br->{td},
|
||||
$br->{previousbuildtime},
|
||||
$br->{buildtime});
|
||||
print "C</a>";
|
||||
}
|
||||
}
|
||||
|
||||
if ($br->{binaryname} ne '') {
|
||||
$binfile = "$buildtree/bin/$buildtime/$br->{buildname}/"
|
||||
."$br->{binaryname}";
|
||||
$binfile =~ s/ //g;
|
||||
print " <a href=$rel_path$binfile>B</a>";
|
||||
}
|
||||
print "</tt>\n</td>";
|
||||
}
|
||||
print "</tr>\n";
|
||||
}
|
||||
|
||||
sub print_table_header {
|
||||
my $ii, $nspan;
|
||||
|
||||
print "<table border=1 bgcolor='#FFFFFF' cellspacing=1 cellpadding=1>\n";
|
||||
|
||||
print "<tr align=center>\n";
|
||||
print "<td rowspan=1><font size=-1>Click time to <br>see changes <br>",
|
||||
"since time</font></td>";
|
||||
print "<td><font size=-1>",
|
||||
"Click name to see what they did</font>";
|
||||
print "<br><font size=-2>",
|
||||
&open_showbuilds_href(rebuildguilty=>'1'),
|
||||
"Rebuild guilty list</a></td>";
|
||||
|
||||
for ($ii=1; $ii <= $name_count; $ii++) {
|
||||
|
||||
my $bn = $build_name_names->[$ii];
|
||||
$bn =~ s/Clobber/Clbr/g;
|
||||
$bn =~ s/Depend/Dep/g;
|
||||
$bn = "<font face='Helvetica,Arial' size=-1>$bn</font>";
|
||||
|
||||
my $last_status = &last_status($ii);
|
||||
if ($last_status eq 'busted') {
|
||||
if ($form{nocrap}) {
|
||||
print "<td rowspan=2 bgcolor=$colormap{busted}>$bn</td>";
|
||||
} else {
|
||||
print "<td rowspan=2 bgcolor=000000 background='$images{flames}'>";
|
||||
print "<font color=white>$bn</font></td>";
|
||||
}
|
||||
}
|
||||
else {
|
||||
print "<td rowspan=2 bgcolor=$colormap{$last_status}>$bn</td>";
|
||||
}
|
||||
}
|
||||
print "</tr><tr>\n";
|
||||
print "<TH>Build Time</TH>\n";
|
||||
print "<TH>Guilty</th>\n";
|
||||
print "</tr>\n";
|
||||
}
|
||||
|
||||
sub print_table_footer {
|
||||
print "</table>\n";
|
||||
|
||||
my $nextdate = $maxdate - $hours*60*60;
|
||||
print &open_showbuilds_href(maxdate=>"$nextdate", nocrap=>'1')
|
||||
."Show next $hours hours</a>";
|
||||
|
||||
print "<p><a href='${rel_path}admintree.cgi?tree=$tree'>",
|
||||
"Administrate Tinderbox Trees</a><br>\n";
|
||||
}
|
||||
|
||||
sub open_showbuilds_url {
|
||||
my %args = (
|
||||
nocrap => "$form{nocrap}",
|
||||
@_
|
||||
);
|
||||
|
||||
my $url = "${rel_path}showbuilds.cgi?tree=$form{tree}";
|
||||
$url .= "&hours=$hours" if $hours ne $default_hours;
|
||||
while (my ($key, $value) = each %args) {
|
||||
$url .= "&$key=$value" if $value ne '';
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
sub open_showbuilds_href {
|
||||
return "<a href=".open_showbuilds_url(@_).">";
|
||||
}
|
||||
|
||||
sub query_ref {
|
||||
my ($td, $mindate, $maxdate, $who) = @_;
|
||||
my $output = '';
|
||||
|
||||
$output = "<a href=${rel_path}../bonsai/cvsquery.cgi";
|
||||
$output .= "?module=$td->{cvs_module}";
|
||||
$output .= "&branch=$td->{cvs_branch}" if $td->{cvs_branch} ne 'HEAD';
|
||||
$output .= "&cvsroot=$td->{cvs_root}" if $td->{cvs_root} ne $default_root;
|
||||
$output .= "&date=explicit&mindate=$mindate";
|
||||
$output .= "&maxdate=$maxdate" if $maxdate ne '';
|
||||
$output .= "&who=$who" if $who ne '';
|
||||
$output .= ">";
|
||||
}
|
||||
|
||||
sub query_ref2 {
|
||||
my ($td, $mindate, $maxdate, $who) = @_;
|
||||
return "${rel_path}../bonsai/cvsquery.cgi?module=$td->{cvs_module}"
|
||||
."&branch=$td->{cvs_branch}&cvsroot=$td->{cvs_root}"
|
||||
."&date=explicit&mindate=$mindate&maxdate=$maxdate&who="
|
||||
. url_encode($who);
|
||||
}
|
||||
|
||||
sub who_menu {
|
||||
my ($td, $mindate, $maxdate, $who) = @_;
|
||||
my $treeflag;
|
||||
|
||||
$qr = "${rel_path}../registry/who.cgi?email=". url_encode($who)
|
||||
. "&d=$td->{cvs_module}|$td->{cvs_branch}|$td->{cvs_root}|$mindate|$maxdate";
|
||||
|
||||
return "<a href='$qr' onclick=\"return who(event);\">";
|
||||
}
|
||||
|
||||
# Check to see if anyone checked in during time slot.
|
||||
# ex. has_who_list(1); # Check for checkins in most recent time slot.
|
||||
# ex. has_who_list(1,5); # Check range of times.
|
||||
sub has_who_list {
|
||||
my ($time1, $time2) = @_;
|
||||
|
||||
if (not defined(@who_check_list)) {
|
||||
# Build a static array of true/false values for each time slot.
|
||||
$who_check_list[$time_count] = 0;
|
||||
my ($t) = 1;
|
||||
for (; $t<=$time_count; $t++) {
|
||||
$who_check_list[$t] = 1 if each %{$who_list->[$t]};
|
||||
}
|
||||
}
|
||||
if ($time2) {
|
||||
for ($ii=$time1; $ii<=$time2; $ii++) {
|
||||
return 1 if $who_check_list[$ii]
|
||||
}
|
||||
return 0
|
||||
} else {
|
||||
return $who_check_list[$time1];
|
||||
}
|
||||
}
|
||||
|
||||
sub tree_open {
|
||||
my $done, $line, $a, $b;
|
||||
open(BID, "<../bonsai/data/$bonsai_tree/batchid")
|
||||
or print "can't open batchid<br>";
|
||||
($a,$b,$bid) = split / /, <BID>;
|
||||
close(BID);
|
||||
open(BATCH, "<../bonsai/data/$bonsai_tree/batch-${bid}")
|
||||
or print "can't open batch-${bid}<br>";;
|
||||
$done = 0;
|
||||
while (($line = <BATCH>) and not $done){
|
||||
if ($line =~ /^set treeopen/) {
|
||||
chop $line;
|
||||
($a,$b,$treestate) = split / /, $line ;
|
||||
$done = 1;
|
||||
}
|
||||
}
|
||||
close(BATCH);
|
||||
return $treestate;
|
||||
}
|
||||
|
||||
sub print_javascript {
|
||||
my $script;
|
||||
($script = <<"__ENDJS") =~ s/^ //gm;
|
||||
<script>
|
||||
if (parseInt(navigator.appVersion) < 4) {
|
||||
window.event = 0;
|
||||
}
|
||||
|
||||
function who(d) {
|
||||
var version = parseInt(navigator.appVersion);
|
||||
if (version < 4 || version >= 5) {
|
||||
return true;
|
||||
}
|
||||
var l = document.layers['popup'];
|
||||
l.src = d.target.href;
|
||||
l.top = d.target.y - 6;
|
||||
l.left = d.target.x - 6;
|
||||
if (l.left + l.clipWidth > window.width) {
|
||||
l.left = window.width - l.clipWidth;
|
||||
}
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
function log_url(logfile) {
|
||||
return "showlog.cgi?log=" + buildtree + "/" + logfile;
|
||||
}
|
||||
function note(d,noteid,logfile) {
|
||||
var version = parseInt(navigator.appVersion);
|
||||
if (version < 4 || version >= 5) {
|
||||
document.location = log_url(logfile);
|
||||
return false;
|
||||
}
|
||||
var l = document.layers['popup'];
|
||||
l.document.write("<table border=1 cellspacing=1><tr><td>"
|
||||
+ notes[noteid] + "</tr></table>");
|
||||
l.document.close();
|
||||
|
||||
l.top = d.y-10;
|
||||
var zz = d.x;
|
||||
if (zz + l.clip.right > window.innerWidth) {
|
||||
zz = (window.innerWidth-30) - l.clip.right;
|
||||
if (zz < 0) { zz = 0; }
|
||||
}
|
||||
l.left = zz;
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
function log(e,buildindex,logfile)
|
||||
{
|
||||
var logurl = log_url(logfile);
|
||||
var commenturl = "addnote.cgi?log=" + buildtree + "/" + logfile;
|
||||
var version = parseInt(navigator.appVersion);
|
||||
|
||||
if (version < 4 || version >= 5) {
|
||||
document.location = logurl;
|
||||
return false;
|
||||
}
|
||||
var q = document.layers["logpopup"];
|
||||
q.top = e.target.y - 6;
|
||||
|
||||
var yy = e.target.x;
|
||||
if ( yy + q.clip.right > window.innerWidth) {
|
||||
yy = (window.innerWidth-30) - q.clip.right;
|
||||
if (yy < 0) { yy = 0; }
|
||||
}
|
||||
q.left = yy;
|
||||
q.visibility="show";
|
||||
q.document.write("<TABLE BORDER=1><TR><TD><B>"
|
||||
+ builds[buildindex] + "</B><BR>"
|
||||
+ "<A HREF=$rel_path" + logurl + ">View Brief Log</A><BR>"
|
||||
+ "<A HREF=$rel_path" + logurl + "&fulltext=1"+">View Full Log</A><BR>"
|
||||
+ "<A HREF=$rel_path" + commenturl + ">Add a Comment</A><BR>"
|
||||
+ "</TD></TR></TABLE>");
|
||||
q.document.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
notes = new Array();
|
||||
builds = new Array();
|
||||
|
||||
__ENDJS
|
||||
print $script;
|
||||
|
||||
$ii = 0;
|
||||
while ($ii < @note_array) {
|
||||
$ss = $note_array[$ii];
|
||||
while ($ii < @note_array && $note_array[$ii] eq $ss) {
|
||||
print "notes[$ii] = ";
|
||||
$ii++;
|
||||
}
|
||||
$ss =~ s/\\/\\\\/g;
|
||||
$ss =~ s/\"/\\\"/g;
|
||||
$ss =~ s/\n/\\n/g;
|
||||
print "\"$ss\";\n";
|
||||
}
|
||||
for ($ii=1; $ii <= $name_count; $ii++) {
|
||||
if (defined($br = $build_table->[1][$ii]) and $br != -1) {
|
||||
my $bn = $build_name_names->[$ii];
|
||||
print "builds[$ii]='$bn';\n";
|
||||
}
|
||||
}
|
||||
print "buildtree = '$form{tree}';\n";
|
||||
|
||||
($script = <<'__ENDJS') =~ s/^ //gm;
|
||||
</script>
|
||||
|
||||
<layer name="popup" onMouseOut="this.visibility='hide';"
|
||||
left=0 top=0 bgcolor="#ffffff" visibility="hide">
|
||||
</layer>
|
||||
|
||||
<layer name="logpopup" onMouseOut="this.visibility='hide';"
|
||||
left=0 top=0 bgcolor="#ffffff" visibility="hide">
|
||||
</layer>
|
||||
__ENDJS
|
||||
print $script;
|
||||
}
|
||||
|
||||
sub do_express {
|
||||
print "Content-type: text/html\nRefresh: 900\n\n<HTML>\n";
|
||||
|
||||
my %build, %times;
|
||||
loadquickparseinfo($form{tree}, \%build, \%times);
|
||||
|
||||
my @keys = sort keys %build;
|
||||
my $keycount = @keys;
|
||||
my $tm = &print_time(time);
|
||||
print "<table border=1 cellpadding=1 cellspacing=1><tr>";
|
||||
print "<th align=left colspan=$keycount>";
|
||||
print &open_showbuilds_href."$tree as of $tm</a></tr><tr>\n";
|
||||
foreach my $buildname (@keys) {
|
||||
print "<td bgcolor='$colormap{$build{$buildname}}'>$buildname</td>";
|
||||
}
|
||||
print "</tr></table>\n";
|
||||
}
|
||||
|
||||
# This is essentially do_express but it outputs a different format
|
||||
sub do_panel {
|
||||
print "Content-type: text/html\n\n<HTML>\n" unless $form{static};
|
||||
|
||||
my %build, %times;
|
||||
loadquickparseinfo($form{tree}, \%build, \%times);
|
||||
|
||||
print q(
|
||||
<head>
|
||||
<META HTTP-EQUIV="Refresh" CONTENT="300">
|
||||
<style>
|
||||
body, td {
|
||||
font-family: Verdana, Sans-Serif;
|
||||
font-size: 8pt;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body BGCOLOR="#FFFFFF" TEXT="#000000"
|
||||
LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
|
||||
);
|
||||
# Hack the panel link for now.
|
||||
print "<a target='_content' href='http://tinderbox.mozilla.org/seamonkey/'>$tree";
|
||||
|
||||
$bonsai_tree = '';
|
||||
require "$tree/treedata.pl";
|
||||
if ($bonsai_tree ne '') {
|
||||
print " is ", tree_open() ? "OPEN" : "CLOSED";
|
||||
}
|
||||
# Add the current time
|
||||
my ($minute,$hour,$mday,$mon) = (localtime)[1..4];
|
||||
my $tm = sprintf("%d/%d %d:%02d",$mon+1,$mday,$hour,$minute);
|
||||
print " as of $tm</a><br>";
|
||||
|
||||
print "<table border=0 cellpadding=1 cellspacing=1>";
|
||||
while (my ($name, $status) = each %build) {
|
||||
print "<tr><td bgcolor='$colormap{$status}'>$name</td></tr>";
|
||||
}
|
||||
print "</table></body>";
|
||||
}
|
||||
|
||||
sub do_flash {
|
||||
print "Content-type: text/rdf\n\n" unless $form{static};
|
||||
|
||||
my %build, %times;
|
||||
loadquickparseinfo($form{tree}, \%build, \%times);
|
||||
|
||||
my ($mac,$unix,$win) = (0,0,0);
|
||||
|
||||
while (my ($name, $status) = each %build) {
|
||||
next if $status eq 'success';
|
||||
$mac = 1, next if $name =~ /Mac/;
|
||||
$win = 1, next if $name =~ /Win/;
|
||||
$unix = 1;
|
||||
}
|
||||
|
||||
print q{
|
||||
<RDF:RDF xmlns:RDF='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
|
||||
xmlns:NC='http://home.netscape.com/NC-rdf#'>
|
||||
<RDF:Description about='NC:FlashRoot'>
|
||||
};
|
||||
|
||||
my $busted = $mac + $unix + $win;
|
||||
if ($busted) {
|
||||
|
||||
# Construct a legible sentence; e.g., "Mac, Unix, and Windows
|
||||
# are busted", "Windows is busted", etc. This is hideous. If
|
||||
# you can think of something better, please fix it.
|
||||
|
||||
my $text;
|
||||
if ($mac) {
|
||||
$text .= 'Mac' . ($busted > 2 ? ', ' : ($busted > 1 ? ' and ' : ''));
|
||||
}
|
||||
if ($unix) {
|
||||
$text .= 'Unix' . ($busted > 2 ? ', and ' : ($win ? ' and ' : ''));
|
||||
}
|
||||
if ($win) {
|
||||
$text .= 'Windows';
|
||||
}
|
||||
$text .= ($busted > 1 ? ' are ' : ' is ') . 'busted';
|
||||
|
||||
# The Flash spec says we need to give ctime.
|
||||
use POSIX;
|
||||
my $tm = POSIX::ctime(time());
|
||||
$tm =~ s/^...\s//; # Strip day of week
|
||||
$tm =~ s/:\d\d\s/ /; # Strip seconds
|
||||
chop $tm;
|
||||
|
||||
print qq{
|
||||
<NC:child>
|
||||
<RDF:Description ID='flash'>
|
||||
<NC:type resource='http://www.mozilla.org/RDF#TinderboxFlash' />
|
||||
<NC:source>$tree</NC:source>
|
||||
<NC:description>$text</NC:description>
|
||||
<NC:timestamp>$tm</NC:timestamp>
|
||||
</RDF:Description>
|
||||
</NC:child>
|
||||
};
|
||||
}
|
||||
print q{
|
||||
</RDF:Description>
|
||||
</RDF:RDF>
|
||||
};
|
||||
}
|
||||
|
||||
sub do_quickparse {
|
||||
print "Content-type: text/plain\n\n";
|
||||
|
||||
my @treelist = split /,/, $tree;
|
||||
foreach my $t (@treelist) {
|
||||
$bonsai_tree = "";
|
||||
require "$t/treedata.pl";
|
||||
if ($bonsai_tree ne "") {
|
||||
my $state = tree_open() ? "Open" : "Close";
|
||||
print "State|$t|$bonsai_tree|$state\n";
|
||||
}
|
||||
my %build, %times;
|
||||
loadquickparseinfo($t, \%build, \%times);
|
||||
|
||||
foreach my $buildname (sort keys %build) {
|
||||
print "Build|$t|$buildname|$build{$buildname}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_rdf {
|
||||
print "Content-type: text/plain\n\n";
|
||||
|
||||
my $mainurl = "http://$ENV{SERVER_NAME}$ENV{SCRIPT_NAME}?tree=$tree";
|
||||
my $dirurl = $mainurl;
|
||||
|
||||
$dirurl =~ s@/[^/]*$@@;
|
||||
|
||||
my %build, %times;
|
||||
loadquickparseinfo($tree, \%build, \%times);
|
||||
|
||||
my $image = "channelok.gif";
|
||||
my $imagetitle = "OK";
|
||||
foreach my $buildname (sort keys %build) {
|
||||
if ($build{$buildname} eq 'busted') {
|
||||
$image = "channelflames.gif";
|
||||
$imagetitle = "Bad";
|
||||
last;
|
||||
}
|
||||
}
|
||||
print qq{<?xml version="1.0"?>
|
||||
<rdf:RDF
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://my.netscape.com/rdf/simple/0.9/">
|
||||
<channel>
|
||||
<title>Tinderbox - $tree</title>
|
||||
<description>Build bustages for $tree</description>
|
||||
<link>$mainurl</link>
|
||||
</channel>
|
||||
<image>
|
||||
<title>$imagetitle</title>
|
||||
<url>$dirurl/$image</url>
|
||||
<link>$mainurl</link>
|
||||
</image>
|
||||
};
|
||||
|
||||
$bonsai_tree = '';
|
||||
require "$tree/treedata.pl";
|
||||
if ($bonsai_tree ne '') {
|
||||
my $state = tree_open() ? "OPEN" : "CLOSED";
|
||||
print "<item><title>The tree is currently $state</title>",
|
||||
"<link>$mainurl</link></item>\n";
|
||||
}
|
||||
|
||||
foreach my $buildname (sort keys %build) {
|
||||
if ($build{$buildname} eq 'busted') {
|
||||
print "<item><title>$buildname is in flames</title>",
|
||||
"<link>$mainurl</link></item>\n";
|
||||
}
|
||||
}
|
||||
print "</rdf:RDF>\n";
|
||||
}
|
||||
|
||||
136
mozilla/webtools/tinderbox/showimages.cgi
Executable file
136
mozilla/webtools/tinderbox/showimages.cgi
Executable file
@@ -0,0 +1,136 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
$| = 1;
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'globals.pl';
|
||||
require 'imagelog.pl';
|
||||
require 'lloydcgi.pl';
|
||||
require 'header.pl';
|
||||
|
||||
check_password();
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
@url = ();
|
||||
@quote = ();
|
||||
@width = ();
|
||||
@height = ();
|
||||
$i = 0;
|
||||
|
||||
EmitHtmlHeader("tinderbox: all images");
|
||||
|
||||
print '<UL>
|
||||
<P>These are all of the images currently in
|
||||
<A HREF=http://www.mozilla.org/tinderbox.html>Tinderbox</A>.
|
||||
<P>Please don\'t give out this URL: this is only here for our debugging
|
||||
needs, and isn\'t linked to by the rest of Tinderbox: because looking at
|
||||
all the images at once would be be cheating! you\'re supposed to let them
|
||||
surprise you over time. What, do you read ahead in your desktop calendar,
|
||||
too? Where\'s your sense of mystery and anticipation?
|
||||
|
||||
<P>
|
||||
</UL>
|
||||
';
|
||||
|
||||
|
||||
|
||||
|
||||
if ($form{'url'} ne "") {
|
||||
$oldname = "$data_dir/imagelog.txt";
|
||||
open (OLD, "<$oldname") || die "Oops; can't open imagelog.txt";
|
||||
$newname = "$oldname-$$";
|
||||
open (NEW, ">$newname") || die "Can't open $newname";
|
||||
$foundit = 0;
|
||||
while (<OLD>) {
|
||||
chop;
|
||||
($url, $width, $height, $quote) = split(/\`/);
|
||||
if ($url eq $form{'url'} && $quote eq $form{'origquote'}) {
|
||||
$foundit = 1;
|
||||
if ($form{'nukeit'} ne "") {
|
||||
next;
|
||||
}
|
||||
$quote = $form{'quote'};
|
||||
}
|
||||
print NEW "$url`$width`$height`$quote\n";
|
||||
}
|
||||
close OLD;
|
||||
close NEW;
|
||||
if (!$foundit) {
|
||||
print "<font color=red>Hey, couldn't find it!</font> Did someone\n";
|
||||
print "else already edit it?<P>\n";
|
||||
unlink $newname;
|
||||
} else {
|
||||
print "Change made.<P>";
|
||||
rename ($newname, $oldname) || die "Couldn't rename $newname to $oldname";
|
||||
}
|
||||
$form{'doedit'} = "1";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$doedit = ($form{'doedit'} ne "");
|
||||
|
||||
if (!$doedit) {
|
||||
print "
|
||||
<form method=post>
|
||||
<input type=hidden name=password value=\"$form{'password'}\">
|
||||
<input type=hidden name=doedit value=1>
|
||||
<input type=submit value='Let me edit text or remove pictures.'>
|
||||
</form><P>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
open( IMAGELOG, "<$data_dir/imagelog.txt" ) || die "can't open file";
|
||||
while( <IMAGELOG> ){
|
||||
chop;
|
||||
($url[$i],$width[$i],$height[$i],$quote[$i]) = split(/\`/);
|
||||
$i++;
|
||||
}
|
||||
close( IMAGELOG );
|
||||
|
||||
$i--;
|
||||
print "<center>";
|
||||
while( $i >= 0 ){
|
||||
$qurl = value_encode($url[$i]);
|
||||
$qquote = value_encode($quote[$i]);
|
||||
print "
|
||||
<img border=2 src='$url[$i]' width='$width[$i]' height='$height[$i]'><br>
|
||||
<i>$quote[$i]</i>";
|
||||
if ($doedit) {
|
||||
print "
|
||||
<form method=post>
|
||||
<input type=submit name=nukeit value='Delete this image'><br>
|
||||
<input name=quote size=60 value=\"$qquote\"><br>
|
||||
<input type=submit name=edit value='Change text'><hr>
|
||||
<input type=hidden name=url value=\"$qurl\">
|
||||
<input type=hidden name=origquote value=\"$qquote\">
|
||||
<input type=hidden name=password value=\"$form{'password'}\">
|
||||
</form>";
|
||||
}
|
||||
print "<br><br>\n";
|
||||
$i--;
|
||||
}
|
||||
|
||||
|
||||
375
mozilla/webtools/tinderbox/showlog.cgi
Executable file
375
mozilla/webtools/tinderbox/showlog.cgi
Executable file
@@ -0,0 +1,375 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib '../bonsai';
|
||||
|
||||
require 'globals.pl';
|
||||
require 'lloydcgi.pl';
|
||||
require 'header.pl';
|
||||
|
||||
#############################################################
|
||||
# Global variables
|
||||
|
||||
$LINES_AFTER_ERROR = 5;
|
||||
$LINES_BEFORE_ERROR = 30;
|
||||
|
||||
# These variables are set by the error parser functions:
|
||||
# has_error(), has_warning(), and has_errorline().
|
||||
$error_file = '';
|
||||
$error_file_ref = '';
|
||||
$error_line = 0;
|
||||
$error_guess = 0;
|
||||
|
||||
$next_err = 0;
|
||||
@log_errors = ();
|
||||
$log_line = 0;
|
||||
|
||||
#############################################################
|
||||
# CGI inputs
|
||||
|
||||
if (defined($args = $form{log}) or defined($args = $form{exerpt})) {
|
||||
|
||||
($full_logfile, $linenum) = split /:/, $args;
|
||||
($tree, $logfile) = split /\//, $full_logfile;
|
||||
|
||||
my $br = find_build_record($tree, $logfile);
|
||||
$errorparser = $br->{errorparser};
|
||||
$buildname = $br->{buildname};
|
||||
$buildtime = $br->{buildtime};
|
||||
|
||||
$numlines = 50;
|
||||
$numlines = $form{numlines} if exists $form{numlines};
|
||||
} else {
|
||||
$tree = $form{tree};
|
||||
$errorparser = $form{errorparser};
|
||||
$logfile = $form{logfile};
|
||||
$buildname = $form{buildname};
|
||||
$buildtime = $form{buildtime};
|
||||
}
|
||||
$fulltext = $form{fulltext};
|
||||
|
||||
$enc_buildname = &url_encode($buildname);
|
||||
|
||||
die "the \"tree\" parameter must be provided\n" unless $tree;
|
||||
require "$tree/treedata.pl";
|
||||
|
||||
$time_str = print_time( $buildtime );
|
||||
|
||||
$|=1;
|
||||
|
||||
if ($linenum) {
|
||||
|
||||
&print_fragment;
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
&print_header;
|
||||
&print_notes;
|
||||
|
||||
# Dynamically load the error parser
|
||||
#
|
||||
die "the \"errorparser\" parameter must be provided\n" unless $errorparser;
|
||||
require "ep_${errorparser}.pl";
|
||||
|
||||
if ($fulltext)
|
||||
{
|
||||
&print_summary;
|
||||
&print_log;
|
||||
}
|
||||
else
|
||||
{
|
||||
$brief_filename = $logfile;
|
||||
$brief_filename =~ s/.gz$/.brief.html/;
|
||||
if (-T "$tree/$brief_filename" and -M _ > -M $tree/$logfile)
|
||||
{
|
||||
open (BRIEFFILE, "<$tree/$brief_filename");
|
||||
print while (<BRIEFFILE>)
|
||||
}
|
||||
else
|
||||
{
|
||||
open (BRIEFFILE, ">$tree/$brief_filename");
|
||||
|
||||
&print_summary;
|
||||
&print_log;
|
||||
}
|
||||
}
|
||||
|
||||
# end of main
|
||||
############################################################
|
||||
|
||||
sub print_fragment {
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
print "<META HTTP-EQUIV=\"EXPIRES\" CONTENT=\"1\">\n";
|
||||
|
||||
my $heading = "Build Log (Fragment)";
|
||||
my $subheading = "$buildname on $time_str";
|
||||
my $title = "$heading - $subheading";
|
||||
|
||||
EmitHtmlTitleAndHeader($title, $heading, $subheading);
|
||||
|
||||
print "<a href='showlog.cgi?tree=$tree&errorparser=$errorparser&logfile=$logfile&buildtime=$buildtime&buildname=$enc_buildname&fulltext=1'>Show Full Build Log</a>";
|
||||
|
||||
open(BUILD_IN, "$gzip -d -c $tree/$logfile|");
|
||||
|
||||
my $first_line = $linenum - ($numlines/2);
|
||||
my $last_line = $linenum + ($numlines/2);
|
||||
|
||||
print "<pre><b>.<br>.<br>.<br></b>";
|
||||
while(<BUILD_IN>) {
|
||||
next if $. < $first_line;
|
||||
last if $. > $last_line;
|
||||
print "<b><font color='red'>" if $. == $linenum;
|
||||
print;
|
||||
print "</font></b>" if $. == $linenum;
|
||||
}
|
||||
print "<b>.<br>.<br>.<br></b></pre>";
|
||||
|
||||
}
|
||||
|
||||
sub print_header {
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
if( $fulltext ){
|
||||
$s = 'Show <b>Brief</b> Log';
|
||||
$s1 = '';
|
||||
$s2 = 'Full';
|
||||
}
|
||||
else {
|
||||
$s = 'Show <b>Full</b> Log';
|
||||
$s1 = 1;
|
||||
$s2 = 'Brief';
|
||||
}
|
||||
|
||||
print "<META HTTP-EQUIV=\"EXPIRES\" CONTENT=\"1\">\n";
|
||||
|
||||
my $heading = "Build Log ($s2)";
|
||||
my $subheading = "$buildname on $time_str";
|
||||
my $title = "$heading - $subheading";
|
||||
|
||||
EmitHtmlTitleAndHeader($title, $heading, $subheading);
|
||||
|
||||
print "
|
||||
<font size=+1>
|
||||
<dt><a href='showlog.cgi?tree=$tree&errorparser=$errorparser&logfile=$logfile&buildtime=$buildtime&buildname=$enc_buildname&fulltext=$s1'>$s</a>
|
||||
<dt><a href=\"showbuilds.cgi?tree=$tree\">Return to the Build Page</a>
|
||||
<dt><a href=\"addnote.cgi?tree=$tree\&buildname=$enc_buildname\&buildtime=$buildtime\&logfile=$logfile\&errorparser=$errorparser\">
|
||||
Add a Comment to the Log</a>
|
||||
</font>
|
||||
";
|
||||
}
|
||||
|
||||
sub print_notes {
|
||||
#
|
||||
# Print notes
|
||||
#
|
||||
$found_note = 0;
|
||||
open(NOTES,"<$tree/notes.txt")
|
||||
or print "<h2>warning: Couldn't open $tree/notes.txt </h2>\n";
|
||||
print "$buildtime, $buildname<br>\n";
|
||||
while(<NOTES>){
|
||||
chop;
|
||||
($nbuildtime,$nbuildname,$nwho,$nnow,$nenc_note) = split(/\|/);
|
||||
#print "$_<br>\n";
|
||||
if( $nbuildtime == $buildtime && $nbuildname eq $buildname ){
|
||||
if( !$found_note ){
|
||||
print "<H2>Build Comments</H2>\n";
|
||||
$found_note = 1;
|
||||
}
|
||||
$now_str = &print_time($nnow);
|
||||
$note = &url_decode($nenc_note);
|
||||
print "<pre>\n[<b><a href=mailto:$nwho>$nwho</a> - $now_str</b>]\n$note\n</pre>";
|
||||
}
|
||||
}
|
||||
close(NOTES);
|
||||
}
|
||||
|
||||
sub print_summary {
|
||||
#
|
||||
# Print the summary first
|
||||
#
|
||||
logprint('<H2>Build Error Summary</H2><PRE>');
|
||||
|
||||
$log_line = 0;
|
||||
open( BUILD_IN, "$gzip -d -c $tree/$logfile|" );
|
||||
while( $line = <BUILD_IN> ){
|
||||
&output_summary_line( $line );
|
||||
}
|
||||
close( BUILD_IN );
|
||||
push @log_errors, 9999999;
|
||||
|
||||
logprint('</PRE>');
|
||||
}
|
||||
|
||||
sub print_log_section {
|
||||
my ($tree, $logfile, $line_of_interest, $num_lines) = shift;
|
||||
local $_;
|
||||
|
||||
my $first_line = $line_of_interest - $num_lines / 2;
|
||||
my $last_line = $first_line + $num_lines;
|
||||
|
||||
print "<a href='showlog.cgi?tree=$tree&logfile=$logfile&line="
|
||||
.($line_of_interest-$num_lines)."&numlines=$num_lines'>"
|
||||
."Previous $num_lines</a>";
|
||||
print "<font size='+1'><b>.<br>.<br>.<br></b></font>";
|
||||
print "<pre>";
|
||||
my $ii = 0;
|
||||
open BUILD_IN, "$gzip -d -c $tree/$logfile|";
|
||||
while (<BUILD_IN>) {
|
||||
$ii++;
|
||||
next if $ii < $first_line;
|
||||
last if $ii > $last_line;
|
||||
if ($ii == $line_of_intested) {
|
||||
print "<b>$_</b>";
|
||||
} else {
|
||||
print;
|
||||
}
|
||||
}
|
||||
close BUILD_IN;
|
||||
print "</pre>";
|
||||
print "<font size='+1'><b>.<br>.<br>.<br></b></font>";
|
||||
print "<a href='showlog.cgi?tree=$tree&logfile=$logfile&line="
|
||||
.($line_of_interest+$num_lines)."&numlines=$num_lines'>"
|
||||
."Next $num_lines</a>";
|
||||
}
|
||||
|
||||
sub print_log {
|
||||
#
|
||||
# reset the error counter
|
||||
#
|
||||
$next_err = 0;
|
||||
|
||||
logprint('<H2>Build Error Log</H2><pre>');
|
||||
|
||||
$log_line = 0;
|
||||
open( BUILD_IN, "$gzip -d -c $tree/$logfile|" );
|
||||
while( $line = <BUILD_IN> ){
|
||||
&output_log_line( $line );
|
||||
}
|
||||
close( BUILD_IN );
|
||||
|
||||
logprint('</PRE><p>'
|
||||
."<font size=+1><a name=\"err$next_err\">No More Errors</a></font>"
|
||||
.'<br><br><br>');
|
||||
}
|
||||
|
||||
sub output_summary_line {
|
||||
my( $line ) = $_[0];
|
||||
my( $has_error );
|
||||
|
||||
$has_error = &has_error( $line );
|
||||
|
||||
$line =~ s/&/&/g;
|
||||
$line =~ s/</</g;
|
||||
|
||||
if( $has_error ){
|
||||
push @log_errors, $log_line + $LINES_AFTER_ERROR;
|
||||
if( ! $last_was_error ) {
|
||||
logprint("<a href=\"#err$next_err\">$line</a>");
|
||||
$next_err++;
|
||||
}
|
||||
$last_was_error = 1;
|
||||
}
|
||||
else {
|
||||
$last_was_error = 0;
|
||||
}
|
||||
|
||||
$log_line++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub output_log_line {
|
||||
my( $line ) = $_[0];
|
||||
my( $has_error, $dur, $dur_min,$dur_sec, $dur_str, $logline );
|
||||
|
||||
$has_error = &has_error( $line );
|
||||
$has_warning = &has_warning( $line );
|
||||
|
||||
$line =~ s/&/&/g;
|
||||
$line =~ s/</</g;
|
||||
|
||||
$logline = '';
|
||||
|
||||
if( ($has_error || $has_warning) && &has_errorline( $line ) ) {
|
||||
$q = quotemeta( $error_file );
|
||||
#$goto_line = ($error_line ? 10 > $error_line - 10 : 1 );
|
||||
$goto_line = ($error_line > 10 ? $error_line - 10 : 1 );
|
||||
$cvsblame = ($error_guess ? "cvsguess.cgi" : "cvsblame.cgi");
|
||||
$line =~ s@$q@<a href=../bonsai/$cvsblame?file=$error_file_ref&rev=$cvs_branch&mark=$error_line#$goto_line $source_target>$error_file</a>@
|
||||
}
|
||||
|
||||
|
||||
if( $has_error ){
|
||||
if( ! $last_was_error ) {
|
||||
$logline .= "<a name=\"err$next_err\"></a>";
|
||||
$next_err++;
|
||||
$logline .= "<a href=\"#err$next_err\">NEXT</a> ";
|
||||
}
|
||||
else {
|
||||
$logline .= " ";
|
||||
}
|
||||
|
||||
$logline .= "<font color=\"000080\">$line</font>";
|
||||
|
||||
$last_was_error = 1;
|
||||
}
|
||||
elsif( $has_warning ){
|
||||
$logline .= " ";
|
||||
$logline .= "<font color=000080>$line</font>";
|
||||
}
|
||||
else {
|
||||
$logline .= " $line";
|
||||
$last_was_error = 0;
|
||||
}
|
||||
|
||||
&push_log_line( $logline );
|
||||
}
|
||||
|
||||
|
||||
sub push_log_line {
|
||||
my( $line ) = $_[0];
|
||||
if( $fulltext ){
|
||||
logprint($line);
|
||||
return;
|
||||
}
|
||||
|
||||
if( $log_line > $log_errors[$cur_error] ){
|
||||
$cur_error++;
|
||||
}
|
||||
|
||||
if( $log_line >= $log_errors[$cur_error] - $LINES_BEFORE_ERROR ){
|
||||
if( $log_skip != 0 ){
|
||||
logprint("\n<i><font size=+1> Skipping $log_skip Lines...</i></font>\n\n");
|
||||
$log_skip = 0;
|
||||
}
|
||||
logprint($line);
|
||||
}
|
||||
else {
|
||||
$log_skip++;
|
||||
}
|
||||
$log_line++;
|
||||
}
|
||||
|
||||
sub logprint {
|
||||
my $line = $_[0];
|
||||
print $line;
|
||||
print BRIEFFILE $line if not $fulltext;
|
||||
}
|
||||
BIN
mozilla/webtools/tinderbox/star.gif
Normal file
BIN
mozilla/webtools/tinderbox/star.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 227 B |
75
mozilla/webtools/tinderbox/tinderbox.spec
Normal file
75
mozilla/webtools/tinderbox/tinderbox.spec
Normal file
@@ -0,0 +1,75 @@
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License
|
||||
# at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
# the License for the specific language governing rights and
|
||||
# limitations under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox CVS Tool rpm spec file.
|
||||
#
|
||||
# The Initial Developer of this code under the MPL is Christopher
|
||||
# Seawood, <cls@seawood.org>. Portions created by Christopher Seawood
|
||||
# are Copyright (C) 1998 Christopher Seawood. All Rights Reserved.
|
||||
|
||||
%define ver SNAP
|
||||
%define perl /usr/bin/perl
|
||||
%define cvsroot /cvsroot
|
||||
%define gzip /usr/bin/gzip
|
||||
%define uudecode /usr/bin/uudecode
|
||||
%define bonsai ../bonsai
|
||||
%define prefix /home/httpd/html/tinderbox
|
||||
# This rpm is not relocateable
|
||||
Summary: automated build tool
|
||||
Name: tinderbox
|
||||
Version: %{ver}
|
||||
Release: 1
|
||||
Copyright: NPL
|
||||
Group: Networking/Admin
|
||||
Source: %{name}-%{ver}.tar.gz
|
||||
BuildRoot: /var/tmp/build-%{name}
|
||||
Requires: bonsai
|
||||
Packager: Christopher Seawood <cls@seawood.org>
|
||||
|
||||
%changelog
|
||||
* Thu Nov 12 1998 Christopher Seawood <cls@seawood.org>
|
||||
- Replaced ver with SNAP
|
||||
|
||||
* Mon Oct 26 1998 Christopher Seawood <cls@seawood.org>
|
||||
- Added MPL header
|
||||
|
||||
* Sun Aug 31 1998 Christopher Seawood <cls@seawood.org>
|
||||
- Made rpm from cvs snapshot
|
||||
|
||||
%description
|
||||
Essentially, Tinderbox is a detective tool. It allows you to see what
|
||||
is happening in the source tree. It shows you who checked in what (by
|
||||
asking Bonsai); what platforms have built successfully; what platforms
|
||||
are broken and exactly how they are broken (the build logs); and the
|
||||
state of the files that made up the build (cvsblame) so you can figure
|
||||
out who broke the build, so you can do the most important thing, hold
|
||||
them accountable for their actions.
|
||||
|
||||
%prep
|
||||
%setup -n %{name}
|
||||
|
||||
%build
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
mkdir -p ${RPM_BUILD_ROOT}%{prefix}/{data,examples}
|
||||
make install PERL=%perl UUDECODE=%uudecode GZIP=%gzip BONSAI=%bonsai CVSROOT=%cvsroot PREFIX=${RPM_BUILD_ROOT}%prefix
|
||||
|
||||
%post
|
||||
echo "Remember to set the admin passwd via '%{bonsai}/data/trapdoor password > %{prefix}/data/passwd"
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr (-, nobody, nobody)
|
||||
%doc README Makefile
|
||||
%{prefix}
|
||||
|
||||
123
mozilla/webtools/tinderbox/viewallnotes.cgi
Executable file
123
mozilla/webtools/tinderbox/viewallnotes.cgi
Executable file
@@ -0,0 +1,123 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
|
||||
use lib '../bonsai';
|
||||
require "globals.pl";
|
||||
require 'lloydcgi.pl';
|
||||
require 'header.pl';
|
||||
|
||||
use Date::Parse;
|
||||
use Date::Format;
|
||||
|
||||
my $TIMEFORMAT = "%D %T";
|
||||
|
||||
$| = 1;
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
my $tree = $form{'tree'};
|
||||
my $start = $form{'start'};
|
||||
my $end = $form{'end'};
|
||||
|
||||
sub str2timeAndCheck {
|
||||
my ($str) = (@_);
|
||||
my $result = str2time($str);
|
||||
if (defined $result && $result > 7000000) {
|
||||
return $result;
|
||||
}
|
||||
print "<p><font color=red>Can't parse as a date: $str</font><p>\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $header = "<table border=1><th>Build time</th><th>Build name</th><th>Who</th><th>Note time</th><th>Note</th>";
|
||||
|
||||
if (defined $tree && defined $start && defined $end) {
|
||||
my $first = str2timeAndCheck($start);
|
||||
my $last = str2timeAndCheck($end);
|
||||
if ($first > 0 && $last > 0) {
|
||||
if (open(IN, "<$tree/notes.txt")) {
|
||||
print "<hr><center><h1>Notes for $tree</H1><H3>from " .
|
||||
time2str($TIMEFORMAT, $first) . " to " .
|
||||
time2str($TIMEFORMAT, $last) . "</H3></center>\n";
|
||||
my %stats;
|
||||
print "$header\n";
|
||||
while (<IN>) {
|
||||
chop;
|
||||
my ($nbuildtime,$nbuildname,$nwho,$nnow,$nenc_note)
|
||||
= split /\|/;
|
||||
if ($nbuildtime >= $first && $nbuildtime <= $last) {
|
||||
my $note = &url_decode($nenc_note);
|
||||
$nbuildtime = print_time($nbuildtime);
|
||||
$nnow = print_time($nnow);
|
||||
print "<tr>";
|
||||
print "<td>$nbuildtime</td>";
|
||||
print "<td>$nbuildname</td>";
|
||||
print "<td>$nwho</td>";
|
||||
print "<td>$nnow</td>";
|
||||
print "<td>$note</td>";
|
||||
print "</tr>\n";
|
||||
if (++$count % 100 == 0) {
|
||||
print "</table>$header\n";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print "<p><font color=red>There does not appear to be a tree " .
|
||||
"named '$tree'.</font><p>";
|
||||
}
|
||||
}
|
||||
print "</table>\n";
|
||||
}
|
||||
|
||||
if (!defined $tree) {
|
||||
$tree = "";
|
||||
}
|
||||
|
||||
if (!defined $start) {
|
||||
$start = time2str($TIMEFORMAT, time() - 7*24*60*60); # One week ago.
|
||||
}
|
||||
|
||||
|
||||
if (!defined $end) {
|
||||
$end = time2str($TIMEFORMAT, time()); # #now
|
||||
}
|
||||
|
||||
print qq|
|
||||
<form>
|
||||
<table>
|
||||
<tr>
|
||||
<th align=right>Tree:</th>
|
||||
<td><input name=tree size=30 value="$tree"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align=right>Start time:</th>
|
||||
<td><input name=start size=30 value="$start"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align=right>End time:</th>
|
||||
<td><input name=end size=30 value="$end"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<INPUT TYPE=\"submit\" VALUE=\"View Notes \">
|
||||
|
||||
</form>
|
||||
|;
|
||||
437
mozilla/webtools/tinderbox/warnings.pl
Executable file
437
mozilla/webtools/tinderbox/warnings.pl
Executable file
@@ -0,0 +1,437 @@
|
||||
#! /usr/bonsaitools/bin/perl
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.1 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is Tinderbox
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1999
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Stephen Lamm <slamm@mozilla.org>
|
||||
|
||||
use FileHandle;
|
||||
|
||||
$tree = 'SeaMonkey';
|
||||
# tinderbox/globals.pl uses many shameful globals
|
||||
$form{tree} = $tree;
|
||||
require 'globals.pl';
|
||||
|
||||
$cvsroot = '/cvsroot/mozilla';
|
||||
$lxr_data_root = '/export2/lxr-data';
|
||||
@ignore = (
|
||||
'long long',
|
||||
'__cmsg_data',
|
||||
'location of the previous definition',
|
||||
'\' was hidden',
|
||||
'declaration of \`index\'',
|
||||
);
|
||||
$ignore_pat = "(?:".join('|',@ignore).")";
|
||||
|
||||
print STDERR "Building hash of file names...";
|
||||
($file_bases, $file_fullpaths) = build_file_hash($cvsroot, $tree);
|
||||
print STDERR "done.\n";
|
||||
|
||||
for $br (last_successful_builds($tree)) {
|
||||
next unless $br->{buildname} =~ /shrike.*\b(Clobber|Clbr)\b/;
|
||||
|
||||
my $log_file = "$br->{logfile}";
|
||||
|
||||
warn "Parsing build log, $log_file\n";
|
||||
|
||||
$fh = new FileHandle "gunzip -c $tree/$log_file |";
|
||||
&gcc_parser($fh, $cvsroot, $tree, $log_file, $file_bases, $file_fullpaths);
|
||||
$fh->close;
|
||||
|
||||
&build_blame;
|
||||
|
||||
my $warn_file = "$tree/warn$log_file";
|
||||
$warn_file =~ s/.gz$/.html/;
|
||||
|
||||
$fh->open(">$warn_file") or die "Unable to open $warn_file: $!\n";
|
||||
&print_warnings_as_html($fh, $br);
|
||||
$fh->close;
|
||||
warn "Wrote output to $warn_file\n";
|
||||
|
||||
last;
|
||||
}
|
||||
|
||||
# end of main
|
||||
# ===================================================================
|
||||
|
||||
sub build_file_hash {
|
||||
my ($cvsroot, $tree) = @_;
|
||||
|
||||
$lxr_data_root = "/export2/lxr-data/\L$tree";
|
||||
|
||||
$lxr_file_list = "\L$lxr_data_root/.glimpse_filenames";
|
||||
open(LXR_FILENAMES, "<$lxr_file_list")
|
||||
or die "Unable to open $lxr_file_list: $!\n";
|
||||
|
||||
use File::Basename;
|
||||
|
||||
while (<LXR_FILENAMES>) {
|
||||
my ($base, $dir, $ext) = fileparse($_,'\.[^/]*');
|
||||
|
||||
next unless $ext =~ /^\.(cpp|h|C|s|c|mk|in)$/;
|
||||
|
||||
$base = "$base$ext";
|
||||
$dir =~ s|$lxr_data_root/mozilla/||;
|
||||
$dir =~ s|/$||;
|
||||
|
||||
$fullpath{"$dir/$base"}=1;
|
||||
|
||||
unless (exists $bases{$base}) {
|
||||
$bases{$base} = $dir;
|
||||
} else {
|
||||
$bases{$base} = '[multiple]';
|
||||
}
|
||||
}
|
||||
return \%bases, \%fullpath;
|
||||
}
|
||||
|
||||
sub last_successful_builds {
|
||||
my $tree = shift;
|
||||
my @build_records = ();
|
||||
my $br;
|
||||
|
||||
|
||||
$maxdate = time;
|
||||
$mindate = $maxdate - 5*60*60; # Go back 5 hours
|
||||
|
||||
print STDERR "Loading build data...";
|
||||
&load_data;
|
||||
print STDERR "done\n";
|
||||
|
||||
for (my $ii=1; $ii <= $name_count; $ii++) {
|
||||
for (my $tt=1; $tt <= $time_count; $tt++) {
|
||||
if (defined($br = $build_table->[$tt][$ii])
|
||||
and $br->{buildstatus} eq 'success') {
|
||||
push @build_records, $br;
|
||||
last;
|
||||
} } }
|
||||
return @build_records;
|
||||
}
|
||||
|
||||
sub gcc_parser {
|
||||
my ($fh, $cvsroot, $tree, $log_file, $file_bases, $file_fullnames) = @_;
|
||||
my $dir = '';
|
||||
|
||||
while (<$fh>) {
|
||||
# Directory
|
||||
#
|
||||
if (/^gmake\[\d\]: Entering directory \`(.*)\'$/) {
|
||||
($build_dir = $1) =~ s|.*/mozilla/||;
|
||||
next;
|
||||
}
|
||||
|
||||
# Now only match lines with "warning:"
|
||||
next unless /warning:/;
|
||||
next if /$ignore_pat/o;
|
||||
|
||||
chomp; # Yum, yum
|
||||
|
||||
my ($filename, $line, $warning_text);
|
||||
($filename, $line, undef, $warning_text) = split /:\s*/, $_, 4;
|
||||
$filename =~ s/.*\///;
|
||||
|
||||
# Special case for Makefiles
|
||||
$filename =~ s/Makefile$/Makefile.in/;
|
||||
|
||||
my $dir = '';
|
||||
if ($file_fullnames->{"$build_dir/$filename"}) {
|
||||
$dir = $build_dir;
|
||||
} else {
|
||||
unless(defined($dir = $file_bases->{$filename})) {
|
||||
$dir = '[no_match]';
|
||||
}
|
||||
}
|
||||
my $file = "$dir/$filename";
|
||||
|
||||
unless (defined($warnings{$file}{$line})) {
|
||||
|
||||
# Special case for "`foo' was hidden\nby `foo2'"
|
||||
$warning_text = "...was hidden " . $warning_text
|
||||
if $warning_text =~ /^by \`/;
|
||||
|
||||
# Remember where in the build log the warning occured
|
||||
$warnings{$file}{$line} = {
|
||||
first_seen_line => $.,
|
||||
log_file => $log_file,
|
||||
warning_text => $warning_text,
|
||||
};
|
||||
}
|
||||
$warnings{$file}{$line}->{count}++;
|
||||
$total_warnings_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub dump_warning_data {
|
||||
while (my ($file, $lines_hash) = each %warnings) {
|
||||
while (my ($line, $record) = each %{$lines_hash}) {
|
||||
print join ':',
|
||||
$file,$line,
|
||||
$record->{first_seen_line},
|
||||
$record->{count},
|
||||
$record->{warning_text};
|
||||
print "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub build_blame {
|
||||
use lib '../bonsai';
|
||||
require 'utils.pl';
|
||||
require 'cvsblame.pl';
|
||||
|
||||
while (($file, $lines_hash) = each %warnings) {
|
||||
|
||||
my $rcs_filename = "$cvsroot/$file,v";
|
||||
|
||||
unless (-e $rcs_filename) {
|
||||
warn "Unable to find $rcs_filename\n";
|
||||
$unblamed{$file} = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
my $revision = &parse_cvs_file($rcs_filename);
|
||||
@text = &extract_revision($revision);
|
||||
while (my ($line, $warn_rec) = each %{$lines_hash}) {
|
||||
my $line_rev = $revision_map[$line-1];
|
||||
my $who = $revision_author{$line_rev};
|
||||
my $source_text = join '', @text[$line-3..$line+1];
|
||||
$source_text =~ s/\t/ /g;
|
||||
|
||||
$who = "$who%netscape.com" unless $who =~ /[%]/;
|
||||
|
||||
$warn_rec->{line_rev} = $line_rev;
|
||||
$warn_rec->{source} = $source_text;
|
||||
|
||||
$warnings_by_who{$who}{$file}{$line} = $warn_rec;
|
||||
|
||||
$total_who_count++ unless exists $who_count{$who};
|
||||
$who_count{$who} += $warn_rec->{count};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub print_warnings_as_html {
|
||||
my ($fh, $br) = @_;
|
||||
my ($buildname, $buildtime) = ($br->{buildname}, $br->{buildtime});
|
||||
|
||||
my $time_str = print_time( $buildtime );
|
||||
|
||||
# Change the default destination for print to $fh
|
||||
my $old_fh = select($fh);
|
||||
|
||||
print <<"__END_HEADER";
|
||||
<html>
|
||||
<head>
|
||||
<title>Blamed Build Warnings</title>
|
||||
</head>
|
||||
<body>
|
||||
<font size="+2" face="Helvetica,Arial"><b>
|
||||
Blamed Build Warnings
|
||||
</b></font><br>
|
||||
<font size="+1" face="Helvetica,Arial">
|
||||
$buildname on $time_str<br>
|
||||
$total_warnings_count total warnings
|
||||
</font><p>
|
||||
|
||||
__END_HEADER
|
||||
|
||||
for $who (sort { $who_count{$b} <=> $who_count{$a}
|
||||
|| $a cmp $b } keys %who_count) {
|
||||
push @who_list, $who;
|
||||
}
|
||||
|
||||
# Summary Table (name, count)
|
||||
#
|
||||
use POSIX;
|
||||
print "<table border=0 cellpadding=1 cellspacing=0 bgcolor=#ededed>\n";
|
||||
my $num_columns = 6;
|
||||
my $num_rows = ceil($#who_list / $num_columns);
|
||||
for (my $ii=0; $ii < $num_rows; $ii++) {
|
||||
print "<tr>";
|
||||
for (my $jj=0; $jj < $num_columns; $jj++) {
|
||||
my $index = $ii + $jj * $num_rows;
|
||||
next if $index > $#who_list;
|
||||
my $name = $who_list[$index];
|
||||
my $count = $who_count{$name};
|
||||
$name =~ s/%.*//;
|
||||
print " " x $jj;
|
||||
print "<td><a href='#$name'>$name</a>";
|
||||
print "</td><td>";
|
||||
print "$count";
|
||||
print "</td><td> </td>\n";
|
||||
}
|
||||
print "</tr>\n";
|
||||
}
|
||||
print "</table><p>\n";
|
||||
|
||||
# Count Unblamed warnings
|
||||
#
|
||||
my $total_unblamed_warnigns=0;
|
||||
for my $file (keys %unblamed) {
|
||||
for my $linenum (keys %{$warnings{$file}}) {
|
||||
$total_unblamed_warnings += $warnings{$file}{$linenum}{count};
|
||||
$warnings_by_who{Unblamed}{$file}{$linenum} = $warnings{$file}{$linenum};
|
||||
}
|
||||
}
|
||||
$who_count{Unblamed} = $total_unblamed_warnings;
|
||||
|
||||
# Print all the warnings
|
||||
#
|
||||
for $who (@who_list, "Unblamed") {
|
||||
my $total_count = $who_count{$who};
|
||||
my ($name, $email);
|
||||
($name = $who) =~ s/%.*//;
|
||||
($email = $who) =~ s/%/@/;
|
||||
|
||||
print "<h2>";
|
||||
print "<a name='$name' href='mailto:$email'>" unless $name eq 'Unblamed';
|
||||
print "$name";
|
||||
print "</a>" unless $name eq 'Unblamed';
|
||||
print " (1 warning)" if $total_count == 1;
|
||||
print " ($total_count warnings)" if $total_count > 1;
|
||||
print "</h2>";
|
||||
|
||||
print "\n<table>\n";
|
||||
my $count = 1;
|
||||
for $file (sort keys %{$warnings_by_who{$who}}) {
|
||||
for $linenum (sort keys %{$warnings_by_who{$who}{$file}}) {
|
||||
my $warn_rec = $warnings_by_who{$who}{$file}{$linenum};
|
||||
print_count($count, $warn_rec->{count});
|
||||
print_warning($tree, $br, $file, $linenum, $warn_rec);
|
||||
print_source_code($linenum, $warn_rec) unless $unblamed{$file};
|
||||
$count += $warn_rec->{count};
|
||||
}
|
||||
}
|
||||
print "</table>\n";
|
||||
}
|
||||
|
||||
print <<"__END_FOOTER";
|
||||
<p>
|
||||
<hr align=left>
|
||||
Send questions or comments to
|
||||
<<a href="mailto:slamm\@netscape.com?subject=About the Blamed Build Warnings">slamm\@netcape.com</a>>.
|
||||
</body></html>
|
||||
__END_FOOTER
|
||||
|
||||
# Change default destination back.
|
||||
select($old_fh);
|
||||
}
|
||||
|
||||
sub print_count {
|
||||
my ($start, $count) = @_;
|
||||
|
||||
print "<tr><td align=right>$start";
|
||||
print "-".($start+$count-1) if $count > 1;
|
||||
print ".</td>";
|
||||
}
|
||||
|
||||
sub print_warning {
|
||||
my ($tree, $br, $file, $linenum, $warn_rec) = @_;
|
||||
|
||||
my $warning = $warn_rec->{warning_text};
|
||||
|
||||
print "<td>";
|
||||
|
||||
# File link
|
||||
if ($file =~ /\[multiple\]/) {
|
||||
$file =~ s/\[multiple\]\///;
|
||||
print "<a href='http://lxr.mozilla.org/seamonkey/find?string=$file'>";
|
||||
print "$file:$linenum";
|
||||
print "</a> (multiple file matches)";
|
||||
} elsif ($file =~ /\[no_match\]/) {
|
||||
$file =~ s/\[no_match\]\///;
|
||||
print "<b>$file:$linenum</b> (no file match)";
|
||||
} else {
|
||||
print "<a href='"
|
||||
.file_url($file,$linenum)."'>";
|
||||
print "$file:$linenum";
|
||||
print "</a> ";
|
||||
}
|
||||
print "</td></tr><tr><td></td><td>";
|
||||
# Warning text
|
||||
print "\u$warning";
|
||||
# Build log link
|
||||
my $log_line = $warn_rec->{first_seen_line};
|
||||
print " (<a href='"
|
||||
.build_url($tree, $br, $log_line)
|
||||
."'>";
|
||||
if ($warn_rec->{count} == 1) {
|
||||
print "See build log excerpt";
|
||||
} else {
|
||||
print "See 1st of $warn_rec->{count} occurrences in build log";
|
||||
}
|
||||
print "</a>)</td></tr>";
|
||||
}
|
||||
|
||||
sub print_source_code {
|
||||
my ($linenum, $warn_rec) = @_;
|
||||
my $warning = $warn_rec->{warning_text};
|
||||
|
||||
# Source code fragment
|
||||
#
|
||||
my ($keyword) = $warning =~ /\`([^\']*)\'/;
|
||||
print "<tr><td></td><td bgcolor=#ededed>";
|
||||
print "<pre><font size='-1'>";
|
||||
|
||||
my $source_text = trim_common_leading_whitespace($warn_rec->{source});
|
||||
$source_text =~ s/&/&/gm;
|
||||
$source_text =~ s/</</gm;
|
||||
$source_text =~ s/>/>/gm;
|
||||
$source_text =~ s|\b\Q$keyword\E\b|<b>$keyword</b>|gm unless $keyword eq '';
|
||||
my $line_index = $linenum - 2;
|
||||
$source_text =~ s/^(.*)$/$line_index++." $1"/gme;
|
||||
$source_text =~ s|^($linenum.*)$|<font color='red'>\1</font>|gm;
|
||||
chomp $source_text;
|
||||
print $source_text;
|
||||
|
||||
print "</font>";
|
||||
#print "</pre>";
|
||||
print "</td></tr>\n";
|
||||
}
|
||||
|
||||
sub build_url {
|
||||
my ($tree, $br, $linenum) = @_;
|
||||
|
||||
my $name = $br->{buildname};
|
||||
$name =~ s/ /%20/g;
|
||||
|
||||
return "../showlog.cgi?log=$tree/$br->{logfile}:$linenum";
|
||||
}
|
||||
|
||||
sub file_url {
|
||||
my ($file, $linenum) = @_;
|
||||
|
||||
return "http://cvs-mirror.mozilla.org/webtools/bonsai/cvsblame.cgi"
|
||||
."?file=mozilla/$file&mark=$linenum#".($linenum-10);
|
||||
|
||||
}
|
||||
|
||||
sub trim_common_leading_whitespace {
|
||||
# Adapted from dequote() in Perl Cookbook by Christiansen and Torkington
|
||||
local $_ = shift;
|
||||
my $white; # common whitespace
|
||||
if (/(?:(\s*).*\n)(?:(?:\1.*\n)|(?:\s*\n))+$/) {
|
||||
$white = $1;
|
||||
} else {
|
||||
$white = /^(\s+)/;
|
||||
}
|
||||
s/^(?:$white)?//gm;
|
||||
s/^\s+$//gm;
|
||||
return $_;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user